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()是从主线程里调用的。