Fork me on GitHub

APP构建之路问题记录


-

2017-04-27 ━ Fragment 中使用 startActivityforResult() 导致 onActivityResult() 中的 request 对不上(二维码扫描订单功能)


- 相关代码:

1
2
3
4
startActivityForResult(intent, ConstantUtil.REQUEST_QR_CODE);
if(requestCode == ConstantUtil.REQUEST_QR_CODE){
}

- 情景还原1:

在 Fragment 中执行

1
getActivity().startActivityForResult(intent,Util.REQUEST_QR_CODE);

跳转新的Activity。

并重写:

1
2
3
4
5
6
7
8
9
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/** 二维码扫描 */
if (resultCode == mActivity.RESULT_OK
&& requestCode == Util.REQUEST_QR_CODE
&& data != null) {
String result = data.getStringExtra("result");
} }

结果是:

onActivityResult中根本没有接收到消息。

BUT: 在 Fragment 所依附的 Activity 中却接收到了消息

- 情景还原2:

在 Fragment 中执行

1
startActivityForResult(intent,Util.REQUEST_QR_CODE);

跳转新的Activity。

并重写:

1
2
3
4
5
6
7
8
9
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
/** 二维码扫描 */
if (resultCode == mActivity.RESULT_OK
&& requestCode == Util.REQUEST_QR_CODE
&& data != null) {
String result = data.getStringExtra("result");
} }

结果是:

onActivityResult中接收到了消息。
在 Fragment 所依附的 Activity 中也接收到了消息

BUT: 在 Fragment 所依附的 Activity 中接收的 requestcode 却不等于 Util.REQUEST_QR_CODE。

- 错误原因:

具体原因这儿有:http://blog.csdn.net/ruancoder/article/details/53490500

我猜 SDK 这样做的目的是:

跳转请求来自于 Fragment,就让反馈消息给 Fragment。
即:startActivityForResult(intent,Util.REQUEST_QR_CODE);
跳转请求来自于 getActivity(),就让反馈消息给 Activity。
即:getActivity().startActivityForResult(intent,Util.REQUEST_QR_CODE);

- 问题解决:

在 Fragment 中使用 情景2 中的代码即可。


-

2017-04-26 ━ 夜间模式开发中碰到的问题


- 问题1:安卓5.0版本以上 AppTheme 的颜色必须使用 RGB(#FFFFFF) 格式,若使用 ARGB(#FFFFFFFF) 格式,报错。

- 问题2-问题描述:

在切换夜间模式的时候,不管使用 setTheme() 方法还是使用 V7 包中的 AppCompatDelegate 类,都不免需要重启当前 Activity,造成屏幕闪烁一次,那么怎么做到平滑切换夜间模式呢?

- 问题解决:

查看了资料网上大多数资料都是在切换的时候截图当前屏幕,然后使用一个渐隐动画消失这张图片,以做到平滑过渡。但是我使用 安卓4.4 的联想手机和 安卓6.0 的小米手机测试都不行,还是会闪烁。

所以我采用下面的方式:

使用一个中间 SwitchActivity 加上进入离开动画作为 MainActivity 自启的中介。

具体见代码和 anim 包下的 xml 动画文件。


-

2017-04-24 ━ recyclerview 包含checkbox 抢夺事件焦点


- 问题描述:

在 recyclerview 的 item 中包含有 checkbox 控件,recyclerview 设置 OnItemClickListener 不生效。倘若使用 addOnItemTouchListener 方法则 item 的点击事件生效,但是当点击 checkbox 时 OnItemTouchListener 方法也会生效。

1、recyclerview 设置 OnItemClickListener 无效。
2、checkbox 设置如下:

android:focusable="false"
android:focusableInTouchMode="false" 

无效。

3、 根布局设置

android:descendantFocusability="blocksDescendants"

无效。

- 错误原因:

类似于 checkbox 、 button 等对焦点具有高优先级的控件,会抢夺父 View 焦点。

- 问题解决:

暂未解决。
-

- 应急方案:

  1. 使用 addOnItemTouchListener 实现 item 的点击事件。 并且在 checkbox 被选择时使用布尔值
    check=true; 标志当前点击是 checkbox 发出的。如果是 checkbox 发出的则 置 check=false; 且在
    onItemClick 方法里面不对此次事件做出任何响应。

  2. 不使用 recycleview 的 item 点击事件,而是在 item 上面添加一个小箭头,点击小箭头即为点击 item,这样
    checkbox 的点击事件和小箭头的点击事件则是独立的。


-

2017-04-22 ━ Litepal 删除数据不成功


- 相关代码:

1
2
3
4
5
6
7
8
9
10
11
@OnClick(R.id.btn_orderall_delete)
public void onClick() {
for(int i=0;i<list.size();i++){
if(list.get(i).isselect()){
list.remove(i);
DataSupport.delete(OrderInfoLitePal.class,i+1);
}
}
LogUtil.e(""+DataSupport.count(OrderInfoLitePal.class));
madapter.notifyDataSetChanged();
}

本来 list 的大小是3,执行 delete 后大小还是3

- 错误原因:

使用 litepal 删除数据时不能根据 list 的 position 作为 delete 的参数 id 进行删除,因为在数据库中我们知道如果使用自增id的话,删除一条数据,它的id是不会变的。比如1、2、3、4、5个自增id,删除id为3的数据,那么现在表大小为4,id分别为1、2、4、5,可见会跳过3。

- 问题解决:

1
2
3
4
5
6
7
8
9
10
11
12
@OnClick(R.id.btn_orderall_delete)
public void onClick() {
for(int i=0;i<list.size();i++){
if(list.get(i).isselect()){
int id=list.get(i).getId();
list.remove(i);
DataSupport.delete(OrderInfoLitePal.class,id);
}
}
LogUtil.e(""+DataSupport.count(OrderInfoLitePal.class));
madapter.notifyDataSetChanged();
}

我们在定义javabean的时候需要自己定义一个 ID 字段,不用设置值,在执行插入操作时litepal会自动为我们的数据插入 ID,然后在删除时使用这个 ID 作为 delete 方法的参数进行删除,成功。


-

2017-04-14 ━ Gson 解析时使用泛型报错 LinkedTreeMap 相关


相关代码:

gson.fromJson(json, clazz)

错误日志:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.qht.blog2.OtherActivity.orderdetail.data.OrderInfoDetailBean

现场还原:

在使用 Gson 解析时,我们使用了封装的 JavaBean ,意味着要使用泛型。在解析的时候正常,解析为 LinkedTreeMap 类型,但是在使用 get 方法取值的时候报错 LinkedTreeMap 不能转化为
JavaBean。

问题解决:

  • 情况1:

    若返回类型为 List 类型,我们采用这种方式解析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 将返回的 List 类型的 Json 字符串解析为 List
* @param <T>
* @param json
* @return
*/
public static <T> List<T> jsonToList(String json,Class<T> clazz) {
if (TextUtils.isEmpty(json) || null == clazz) {
return null;
}
List<T> list = new ArrayList<T>();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for(final JsonElement elem : array){
list.add(gson.fromJson(elem, clazz));
}
return list;
}
  • 情况2:(我采用的方法二,很明显是很笨的方法,所有希望能找个更好的方法。)

    若返回类型为 Model 类型,并且里面包含 list,例如:

1
2
3
4
5
6
7
8
9
10
public class OrderInfoBean<T> extends CommBean{
String message;
String nu;
String ischeck;
String condition;
String com;
String status;
String state;
private List<T> data;

我们先解析为正常 model,然后通过 getdata 方法拿到这个 list ,然后通过下面的方法先转换为 String:

1
2
3
4
5
public static <T> String ListTojson(List<T> T) {
String jsonStr = gson.toJson(T);
return jsonStr;
}

再然后通过下面的方法再解析一次,便可以得到正常的 List ,而非 LinkedTreeMap。


-

2017-04-13 ━ Android Studio compile时导致重复包


- 相关代码:

compile ‘com.android.support:support-v4:24.2.1’
compile (‘com.android.support:appcompat-v7:24.2.1’)
{exclude module: ‘support-v4’}

- 错误日志:

Error converting bytecode to dex: Cause: com.android.dex.DexException:
Multiple dex files define Landroid/support/v4/accessibilityservice/
AccessibilityServiceInfoCompatIcs;

- 现场还原:

在我们 compile 导入依赖包的时候某些包也许恰恰依赖了 support-v4 包,然后导致上面的错误,意思是存在多个相同的类 AccessibilityServiceInfoCompatIcs,这就是因为我们的v4包重复了。

- 问题解决:

  • 方法1:

这里写图片描述

这里写图片描述

这里写图片描述

选择 Project,点击 External Libraries,可以看到,我们不止有重复的v4包,还有drawable包也重复了。第一种方法便是

这里写图片描述

在你的 App build 文件中添加 mutiDexEnabled true,支持多Dex文件,但是这样会导致编译过慢,所以我们还需要在你的 APP build 文件的添加:

1
2
3
4
5
android {
dexOptions {
preDexLibraries = false
}
}

增加编译速度。

  • 方法2:

第二种方法呢,是在出现问题的 compile 包下面添加例如:

1
2
compile ('com.android.support:appcompat-v7:24.2.1')
{ exclude module: 'support-v4' }

意思是移除这个包所引用的v4包,完了之后 clean 再编译。

  • 方法3(特例):
1
2
3
compile 'com.android.support:support-v4:24.2.1'
compile ('com.android.support:appcompat-v7:24.2.1')
{ exclude module: 'support-v4' }

如上所示,首先在所有的 compile 下面写上 { exclude module: 'support-v4' }这段代码,clean 一下,然后删除刚才的所有 exclude ,再重新引入v4和v7包,并且在v7包下 exclude v4包,再 clean。意思是使用这个v4包代替其他包下的v4包,最后 clean 并且 build。


-

2017-04-09 ━ EventBus 发布事件不能被接收


- 相关代码:

EventBus.getDefult().register(subscriber);

- 现场还原:

在 fragment 注册 eventbus 时参数为 getactivity,导致 fragment 内部的 onEvent 方法不能接收post 出的事件,而被 activity 接收。

- 问题解决:

fragment 在注册是参数填写 this,而不是 getActivity。

如果参数为 getActivity,表示注册事件到依附的 activity。在 post 事件的时候而导致父类 activity 或者所依附的 activity 截获 post 事件,引起本 fragment 不能正常接收。

所以注册时参数为当前类,或者直接填写 this,不论任何类,首先保证在本类生效。