1.Android java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
E/AndroidRuntime(7200): Uncaught handler: thread Thread-8 exiting due to uncaught exception E/AndroidRuntime( 7200): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。
解决方法:
new Thread() {
public void run() {
Looper.prepare();
mPst.startPushService();
mPst.sendJson2Server(qJson);//上线发消息给server
Looper.loop();
}
}.start();
加上上面红色两行。
2.java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131362336, class android.widget.ListView) with Adapter(class com.manjay.housebox.slidemenu.SpecialListFragment$SpecialAdapter)]
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131362336, class android.widget.ListView) with Adapter(class com.manjay.housebox.slidemenu.SpecialListFragment$SpecialAdapter)]
错误的大体意思是:你的adapter的内容变化了,但是你的ListView并不知情。请保证你adapter的数据在主线程中进行更改!
解决方法:
1、检查Thread,确定没有在Background thread中直接调用adapter,如果有,请移除相关代码到Handler中处理;
2、尽量将数据放在adapter类中管理,不需要的时候清除信息(勤写clear()),及时用notifyDataSetChanged()刷新;
3、在Activity或者Fragment合适的位置(onPause/onStop)要及时检查thread,有adapter数据处理相关的应马上停止;
4、这个错误经常出现在Activity休眠起来之后,主要还是使用adapter不太小心造成的。如果实在找不到原因,在onPause()函数中停止所有的background thread,并且在onResume()函数最前面清空adapter中的数据,并且adapter.notifyDataSetChanged()。然后重新更新加载数据,这样一般可以解决问题。
经过尝试,问题最终通过第二种方法解决了。
实现方法如下:
class SpecialAdapter extends BaseAdapter { //将数据集合转移到适配器里 private ArrayList<SpecialInfo> dataList; @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = getActivity().getLayoutInflater(); convertView = inflater.inflate(R.layout.speciallist_item, null); } ImageView iv_main = ViewHolder.get(convertView, R.id.speciallist_item_image); TextView tv_title = ViewHolder.get(convertView, R.id.speciallist_item_title); SpecialInfo data = dataList.get(position); if (position == 0) { layoutView.setVisibility(View.GONE); } else { layoutView.setVisibility(View.VISIBLE); } Bitmap bm = BitmapFactory.decodeResource(getActivity().getResources(), data.icon); iv_main.setImageBitmap(bm); tv_title.setText(data.title); return convertView; } @Override public int getCount() { return dataList == null ? 0 : dataList.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } //更新数据 public void setDataList(ArrayList<SpecialInfo> list) { if (list != null) { dataList = (ArrayList<SpecialInfo>) list.clone(); notifyDataSetChanged(); } } //释放数据 public void clearDataList() { if (dataList != null) { dataList.clear(); } notifyDataSetChanged(); } }
注:
1.将所有数据“完全”保存在adapter内部,即使有外部数据进入,也会用.clone()重新生成副本,保证了数据完全是由adapter维护的。
2.保证所有setDeviceList()/clearDeviceList()是从主线程里调用的。