一:mvvm模式中使用协程和线程,activity调用vm时使用listener(listener回调之前,activity finish)的情况
1:协程。delay5秒调用回调。如过activity finish了。协程会直接取消,不会进行回调。如果把delay(5)改成5个delay(1),并分别打印1,2,3,4,5。会在activity finish时停留在当前delay处不再继续执行
2:线程。Thread直接跑的话会触发回调。如果activity finish后,其中设置的listener,操作ui,比如给文本设置文字这种也不会崩溃,activity虽然destoryl了,但是activity对象本身没有释放。包括listener中回调启动activity依然会触发。这种需要谨慎处理,如果处理依托activity的一些操作,比如弹窗之类或者fragment之类的,可能就会报错。但是1中的情况基本可以放心写任何操作,因为不会回调。另外mvvm是数据推动ui,不管协程还是线程都可以 不进行listener操作,直接改变一个数据,activity观察数据进行操作,这样不管是协程还是线程 延时操作中如果activity销毁(观察者销毁,不再对数据进行观察),也是可以放心写操作的。
二:比较奇葩的现象,部分手机会出现
1.情景:进入页面时edittext默认获取焦点,显示光标,出现键盘.。经过各种尝试,大部分手机是可以的,但是部分手机显示键盘,但不显示光标,同时输入能容可以上到edittext。很奇怪,后来对比后发现设置了transitionName 使用了过场动画导致的,去掉后可以正常显示光标:(
三:日期转换 不确定格式String转date或long。
1.情景,服务器在各个页面返回的日期不一样,可能是yyyy-MM-dd ;yyyy-MM;或者带时分秒等。并且业务变化时时间可能也会变,这边用一种可能会牺牲一些效率,但是维护方便一些的方案。就是指提供一个方法,遍历定义好的日期形式的数组,逐个转换,直到不发生异常的那个代表匹配成功。考虑到 即使再多样,一个app中也就3/4种展示形式,可以使用这个方案。当然精准 匹配的话,需要服务器和客户端一致同步,否则就会出错。。;当然也可以 让服务器同步返回farmat的字符串(服务器方便沟通的情况下)
四:EditText按回车按键后出现 focus search returned a view that wasn't able to take focus! 错误
因为在按下回车键后,焦点会自动切换到下一个EditText上.这个时候如果你隐藏或者本身未加载下一个EditText.就出现这个报错. 报错的意思就是我的焦点目标丢失了,找不到下一个EditText.在EditText属性里设置 android:imeOptions="actionUnspecified" . imeOptions就是控制回车键具体作用的属性。或者 重写action事件
mEditView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return true;
}
});
五:使用databinding时 edittext控件 使用android:text="@=item.name"这种方式获取,activity中oncreate中对livedata赋值(上个界面传进来的默认值),edittext显示后光标会在前面
如果我们从getintent中获取的name直接用edittext.settext方式,光标是在后面的。使用问题描述的情况就会跑前面去。同时做了个验证,如果使用普通的settext,但是使用延时方式比如Handle().postdelay()去settext。光标也会跑前面去。当然如果普通方式不延时光标在后面 ,但比如点击一个按钮在settext光标也会跑前面。因为databinding是属于观察者模式,(没细细追究)可能属于延时了。言归正传,经尝试使用如下方案可以解决这个问题:
mViewModel.getText().setValue(mValue);
mBinding.setModel(mViewModel);
mBinding.executePendingBindings();
mBinding.etEdit.requestFocus();
需要注意的时,livedata需要使用setvalue不能使用postvalue,如上,完。
六、android10以上后台启动activity无效引发得问题
设计一个api,异步做一些事情,然后弹出一个页面,页面内操作成功,通过listener通知外面,外面再做一些后续得事情。但是如果调用了api后,home放入了后台。线程依然在跑,跑到了startActivity这里,也没有异常,但就是没有启动activity,也不知道它并没有启动,所以也无法通过listener告诉外界任何事情,这个listener就被吃掉了。比如我白屏页调用login得api(自动登录),如果失败我就显示登录页,如果成功就进入首页。但是回调被吃掉了,就停留在白屏页了。比如微信,如果弱网它有个loading,如果home之后即使网络好了,它也无法启动WxEntryActivity来告知app结果。 产品不一定会设计白屏页等待这种情况,但我做得时候sdk,无法约束接入者得接入形式,对方接入时确实就使用得上面得流程,作为sdk方也不好让人改对接方式。
经过尝试,感觉有两种方式可以感知是否startAct成功了,一个是用startActforResult,调用了api如果页面未启动成功也会有一个resultcode代表cancel了。 二是 startAct前做一个监听,因为start是很快得,2秒发现没启动就可以认为 启动失败了(之前好像有个后台会延时5秒启动act的情况,这个也需要再调研下,思路就是这样的)
七、Gson 如果字符串是[]这种结果,无法传Arraylist<ClassXXX>.class。需要使用from(string,TypeToken<ArrayList<ClassXX>>(){}.getType())这种,TypeToken包装泛型后再去解析它的type