在listView中显示json数据出现的问题及解决方法
问题描述:在listView中加载解析的json数据,出现了一种很奇怪的现象:解析的json数据在模拟器中能够正常显示,但是却在真机中无法显示,一片空白
问题分析:原因是请求网络数据是异步的,程序在解析json数据时,仍然会往下执行,导致json数据还没解析完就提前执行了adapter对象的创建,导致在创建adapter对象时传入的newsList大小为空,于是没有任何数据显示
new Thread(new Runnable() {
@Override
public void run() {
getNewsInfo();//这里在进行json数据解析
}
}).start();
NewsAdapter adapter = new NewsAdapter(MainActivity.this, R.layout.listview_item, newsList);
listView.setAdapter(adapter);
解决方案:使用异步消息处理机制,在解析完json数据获取到newsList后,利用handler将消息抛出,然后在处理消息函数handleMessage()中创建adapter并设置listView的adapter
try {
//解析json数据,一定要在子线程中解析json数据
JSONObject ob = new JSONObject(jsonData);
JSONArray newslist = ob.getJSONArray("newslist");
JSONObject content = null;
for (int j = 0; j < newslist.length(); j++) {
content = newslist.getJSONObject(j);
String ctime = content.getString("ctime");
String title = content.getString("title");
News news = new News(R.drawable.apple_pic, title, ctime);
newsList.add(news);
Log.i("sdkdemo", ctime);
Log.i("sdkdemo", title);
}
//解析json数据后抛出消息
Message message = new Message();
message.what = UPDATE;
handler.sendMessage(message);
} catch (JSONException e) {
e.printStackTrace();
}
listView = (ListView) findViewById(R.id.list_view);
new Thread(new Runnable() {
@Override
public void run() {
getNewsInfo();//解析json数据
}
}).start();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what)
{
case UPDATE:
NewsAdapter adapter = new NewsAdapter(MainActivity.this, R.layout.listview_item, newsList);
listView.setAdapter(adapter);
break;
default:
break;
}
}
};
这时,只有在解析json数据后才会执行adapter的创建,不会导致传入的newsList为空
扩展:异步消息处理机制可以解决子线程更新UI的问题,在子线程中不能够更新UI的,可以利用异步消息处理机制来解决。
异步消息处理机制原理:更新UI的操作需要在主线程中运行。当子线程需要更新UI时,创建一个Message消息,利用handler将消息发送出去,之后这条消息就会被添加到MessageQueue的队列中等待被处理,而Looper就会一直尝试从MessageQueue中取出待处理消息,最后分发回handler的handlerMessage()方法中。由于Handler是在主线程中创建的,所以此时handlerMessage()方法也在主线程中执行,那么就可以进行UI操作了。