android-cn/topics

你在工作中遇到的最复杂的问题或者 Bug 是什么?你是怎么搞定的?

Trinea opened this issue · 25 comments

@chriszeng87 提供,方便的话,请大家详细描述场景以及解决方案

1.看运行错误 ,闪退啊,还是什么提示 .根据以往经验
2.看 log.如果知道 .就去改. 不知道 去谷歌
3.单步调试.
4.朋友求助

最近碰到的是想把FragmentTabHost给它弄个透明背景。整了一晚上没弄成。时间有限于是暂时放弃了- -过段时间接着整。

@330939204 你应用市场搜索一下“1元夺宝”这个app的底部tab是不是你想要的效果?是的话我把代码贴给你

想要自定义一个 ImageView,让它在按下的时候蒙上一层阴影。
蒙阴影并不复杂,调用 Drawable 的setColorFilter方法即可。监控按下抬起也不复杂,无论是 setOnTouchEventListener 还是override onDispatchTouchEvent 方法,针对 Down Event 加阴影,Up 或 Cancel Event清除阴影即可。
问题是,把这么一个自定义控件放到GridView 里面, 并给 GridView 设置 onItemClickListener 时,你按下这个自定义控件,它会蒙上阴影,但是你抬起的时候,阴影不会消失。原因是这种情况下,自定义控件接收不到Up 或 Cancel Event。不能简单的在接收到 Down Event 的时候返回 true,那样的话会导致很多上层视图无法正常工作。
我的解决办法是,自定义了一个配套的GridView,它在恰当的时候会创建 Down Event 和 Up Event,然后传递给恰当的 ItemView。让你在充满图片 GridView上面滑动的时候,手指移到一张图片上面,它就会加上阴影。从它上面移开,阴影就会消失。最终效果如下所示
my_color_filter_grid_view

@cavabiao 是这个效果呢。我最近也做到了这个。

我把r17的v4包更新到了r22,r22里面的fragmenttabhost把real content放到了fragmenttabhost内部(如果布局时在tabhost外部指定一个framelayout作为real content会报错),所以就相当于用tabhost包住了整个页面,在里面我放了一个relativeLayout,把real content的framelayout放到tab content的framelayout下面,再给tab content设置半透明背景就可以做到这个效果。

<android.support.v4.app.FragmentTabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:background="@color/transparent" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/transparent"
        android:orientation="vertical" >

        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:background="#f2ffffff" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:background="@color/transparent"
                android:divider="@color/transparent" />
        </FrameLayout>
    </RelativeLayout>
</android.support.v4.app.FragmentTabHost>

比较好奇的是原来使用把fragmenttabhost叠放在real content的上面的时候,tabhost设置背景为半透明会无效的原因是啥。原来的方法是这样:

    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="@color/transparent" >

        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentBottom="true"
            android:background="#f2ffffff" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:background="@color/transparent"
                android:divider="@color/transparent" />
        </FrameLayout>
    </android.support.v4.app.FragmentTabHost>
</RelativeLayout>

不知道你的实现方法是怎样,希望也可以学习一下。

👍

@myronlee 可以看看代码么。

@aheadlcx

package com.sinaapp.myron.colorfilterimageviewdemo.widget;

import android.content.Context;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridView;

public class ColorFilterGridView extends GridView {

    private int prePosition = -1;

    public ColorFilterGridView(Context context) {
        super(context);
    }
    public ColorFilterGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public ColorFilterGridView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int action = event.getAction();

        int curPostion = pointToPosition(((int) event.getX()), ((int) event.getY()));
        if (curPostion == -1 && prePosition != -1){
            cancelItemViewAt(prePosition, event);
        } else if (curPostion != -1 && prePosition ==-1){
            downItemViewAt(curPostion, event);
        } else if (curPostion != -1 && prePosition != -1 && curPostion != prePosition){
            downItemViewAt(curPostion, event);
            cancelItemViewAt(prePosition, event);
        }
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                prePosition = curPostion;
                break;
            case MotionEvent.ACTION_MOVE:
                prePosition = curPostion;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (curPostion != -1){
                    cancelItemViewAt(curPostion, event);
                }
                prePosition = -1;
                break;

            default:
                break;
        }

        return super.dispatchTouchEvent(event);
    }

    private void downItemViewAt(int position, MotionEvent event) {
        View itemView = getChildAt(position - getFirstVisiblePosition());

        MotionEvent cancelEvent = MotionEvent.obtain(event);
        cancelEvent.setAction(MotionEvent.ACTION_DOWN | (event.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));
        itemView.dispatchTouchEvent(cancelEvent);
    }

    private void cancelItemViewAt(int position, MotionEvent event) {
        View itemView = getChildAt(position - getFirstVisiblePosition());

        MotionEvent cancelEvent = MotionEvent.obtain(event);
        cancelEvent.setAction(MotionEvent.ACTION_CANCEL | (event.getActionIndex()<< MotionEvent.ACTION_POINTER_INDEX_SHIFT));
        itemView.dispatchTouchEvent(cancelEvent);
    }
}
package com.sinaapp.myron.colorfilterimageviewdemo.widget;

import android.content.Context;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;


public class ColorFilterImageView extends ImageView {

    public ColorFilterImageView(Context context) {
        this(context, null, 0);
    }

    public ColorFilterImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ColorFilterImageView(Context context, AttributeSet attrs,
                                int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        int action = event.getAction();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                getDrawable().setColorFilter(0x80000000, Mode.SRC_ATOP);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                getDrawable().clearColorFilter();
                invalidate();
                break;

            default:
                break;
        }
        return super.dispatchTouchEvent(event);
    }

}

今天刚遇到一个问题,在Android的webview中是不支持input type="file"标签的。
解决方案是:重写Android的WebChromeClient, 实现openFileChooser方法(考虑几个不同Android版本实现的方式),另外,Android4.4的onActivityResult的data是不能直接拿到Image文件的,要进行转化。
http://david-wei.github.io/2015/07/07/Webview-%E6%94%AF%E6%8C%81-input-type-file/

使用WebView加载有些H5页面导致部分手机(三星note3,三星note4,小米3,红米)直接崩溃 log显示底层so库报错,还不清楚具体的出错原因,猜测是渲染的问题

@david-wei 之前遇到和图片传送有关的是intent 的byte[] 是有大小限制的, 在一个80kb左右的区间,而且没有exception只有在logcat里面非常小的一列红字。

@myronlee
public class AlphableBitmapDrawable extends BitmapDrawable {

private static final int MASK_COLOR = 0x77000000;
private boolean isEnable = true ;
public AlphableBitmapDrawable(Resources res, Bitmap bitmap) {
    super(res, bitmap);
    this.setState(new int[]{android.R.attr.state_pressed, android.R.attr.state_selected, android.R.attr.state_enabled});
}

public AlphableBitmapDrawable(Resources res, Bitmap bitmap,boolean enable) {
    this(res, bitmap);
    isEnable = enable ;
}

@Override
protected boolean onStateChange(int[] states) {
    if(isEnable){
        for (int state : states) {
            if (state == android.R.attr.state_pressed) {
                setColorFilter(new PorterDuffColorFilter(MASK_COLOR, PorterDuff.Mode.SRC_ATOP));
            } else if (state == android.R.attr.state_selected) {
                setColorFilter(null);
            } else if (state == android.R.attr.state_enabled) {
                setColorFilter(null);
            }
        }
    }
    return true;
}

@Override
public boolean isStateful() {
    return true;
}

public void setEnableAlpha(boolean flag){
    isEnable = flag;
}

public class AlphaImageView extends ImageView {
......
@OverRide
public void setImageDrawable(Drawable drawable) {
if(drawable!=null && drawable != getDrawable()){
Bitmap bitmap = null;
if (drawable instanceof BitmapDrawable)
bitmap = ((BitmapDrawable) drawable).getBitmap();
if (bitmap != null) {
drawable = new AlphableBitmapDrawable(getResources(),bitmap) ;
}
}
super.setImageDrawable(drawable);
}
}

@411805662 good, same to you~

App里面有一个存在了半年多的BUG,偶尔发生,后来在解决其他BUG的时候不小心解决掉了,是因为重写了onSaveInstanceState造成的,少保存了一个数据。PS:这个BUG是前一个员工写出来的,我接手的

今天刚遇到一个bug,在一个view使用setBackgroundColor设置了颜色后,在一个低内存的mi 1手机上,这个view的页面finish后,打开其他页面时,会出现新页面的view的背景色是之前setBackgroundColor设置的颜色。然而这个bug在其他手机上不会出现。真是百思不得解。。。最后把setBackgroundColor改成setBackgroundResource就可以了。。

@cruise1008 搞不好是小底层米搞得的问题,之前在复写dialog的dismiss方法时独立出来一个dismissDialog方法,然后就出现了神奇的现象,栈溢出...,小米4还有,晕死

4.1.2系统上,打开webview以后,首页toolbar的view会消失一个; 目前还无解,好在4.1.2系统手机几乎不太有了。

产品让做一个有如下功能的页面,支持toolbar透明+头部+上滑悬浮条(tabLayout)+viewpager(含三个tab,各自支持上拉加载)。效果如下
screenshot_2016-06-25-22-15-28_cn com nggirl ngus

本来想当然地认为CollapsingToolbarLayout+AppBarLayout可以标悬浮tablayout并做出toolbar折叠的透明渐变效果,但是写起来才发现到处都是坑。

由于项目其他模块使用的是PullToRefreshListView,但是它不能很好的和CollapsingToolbarLayout协作,导致滑动列表时有卡顿,甚至出现瞬间快速滑动的问题。本来想改成RecyclerView,但是它又不支持上拉加载的功能,同时很难做出PullToRefreshListView的那种“很丑”的上拉拖拽动画效果,这种效果虽然丑,但是产品坚持要做理由是为了和其他页面“统一”,所以使用RecyclerView的路就断了。

一顿折腾之后才明白,material风格的组件要慎用,国内的设计师基本是拿IOS的设计图让android来实现的,使用了material之后会出现很多坑,比如上面说的卡顿的问题,还有就是设计对CollapsingToolbarLayout折叠时的效果不满意,说不够流畅。

为了解决上面的卡顿的问题,我找到了一个不错的demo,RefreashTabView,但是无奈每天任务都排满了,没时间迁移过去,也不知道有多少坑。有做过类似风格的大神还请分享下经验。

标题 : WebView动态加载本地图片

问题:

app 加载 一元夺宝的H5页面,夺宝成功后,页面当中有一个评价晒单的按钮,
点击该按钮后,需要调起android 手机的相册,让用户去选取图片,
当用户选好图片后需要把图片回传给H5页面以显示出来。

最终解决方案:

android 代码 :

public static final String JS_METHOD_SET_IMG = "javascript:setImag('%s')";
public static final String PREFIX_IMG_DADA = "data:image/png;base64,";

File imgFile = new File(imgFilePath);
InputStream imgInputStream = new FileInputStream(imgFile);
String imgData = new String(Base64.encode(toByteArray(imgInputStream),Base64.DEFAULT));
mWebView.loadUrl(String.format(JS_METHOD_SET_IMG,PREFIX_IMG_DADA+imgData));

js 代码 

function setImag(data){
        document.getElementById("img_id").src=""+data
}

activity进入后台被系统kill后,再通过其他应用A启动这个activity时这个activity接收不到A应用传过来的intent。

跳个台,想练手AppBarLayout,然后跑出来后在genymotion上滑来滑去见不到与CoordinatorLayout配合的收缩效果,以为版本问题,调target,不成,上真机,ok,原来是我用触摸板的双指滑动了,没拖动。。。。但是目前发现知乎的app反而可以在双指滑动下隐藏appbarlayout,还在在找问题

最复杂的问题吗? 我觉得是保活了。
怎么解决的? 感觉是无解。
围绕三个话题吧
1.活着怎么尽量让它不死
2.死了怎么努力把它唤醒
3.你能做什么和 你的用户能帮你做什么

段子

有人说有朋友用电脑播放青藏高原这首歌的时候 特别是放到“那就是青藏高...”时
就会死机 是说硬盘产生了共振,振幅过大,读写头读不出数据了。

最近项目上用户反馈一些手机上比如锤子 华为特定机型 还有一些奇葩手机通话录音无法在后台管理 也就是网页上听 要么就是找不到录音文件 还有一小部分统计上面出现误差

最近项目上用户反馈一些手机上比如锤子华为特定机型还有一些奇葩手机通话录音无法在后台管理也就是网页上听要么就是找不到录音文件还有一小部分统计上面出现误差

大部分机型 或者常用的机型 都没有问题