在Android應用中,如果ListView或是GridView裡面的資料比較多的時候,載入會比較費時間,特別是裡面有圖片的時候,需要花費的時間就更長,這樣就會出現一個長時間的等待黑屏介面,這樣有時會給使用者造成一種錯覺,就是這個程式已經“死”了,,,
對於這個問題可以的一個方法是,添加一個ProgressDialog,顯示正在處理的視窗,等待載入完之後再關閉這個視窗,
但是這樣等所有的資料載入完之後,就是特別突然的顯示, 這樣使用者體驗也不佳,
以前看Android最佳化大師的時候,開啟進程管理的時候,它是前面顯示正在載入的ProgressDialog,然後也可以看到背景資料正在逐條載入,這樣給人的感覺就好很多,現在就是要做這個效果~~~~
主要實現的思路是這樣的,建立一個線程,然後線上程裡面擷取已經安裝的程式,再逐條把這些程式(資料)添加到緩衝數組中,再發送一個訊息,更新顯示ListView的內容,當線程中所有的資料已經載入完的時候,再把ProgressDialog關掉,總的完成效果如下:
程式原始碼
package com.sf.test; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.KeyEvent; import android.widget.ArrayAdapter; import android.widget.ListView; /** * @author Yao.GUET * blog: http://blog.csdn.net/Yao_GUET * 實現動態載入一個ListView */ public class ProcessorBarTest extends Activity { public static final int MSG_UPDATE_LIST = 18; private ListView mApps; private Context mContext; private List<String> mAppList; private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.processorbar_test); // ListView 列表 mApps mApps = (ListView)findViewById(R.id.lvProcessbar); mContext = this; mAppList = new ArrayList<String>(); // 設定正在處理視窗 dialog = new ProgressDialog(mContext); dialog.setIcon(R.drawable.icon); dialog.setTitle("ProgressDialog"); dialog.setMessage("Please wait while loading application list..."); dialog.setCancelable(false); dialog.show(); // 開始動態載入線程 mThreadLoadApps.start(); } private Thread mThreadLoadApps = new Thread(){ @Override public void run() { int i = 0; // TODO Auto-generated method stub // 擷取已經安裝程式列表 PackageManager pm = mContext.getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); // 逐項添加程式,並發送訊息更新ListView列表。 for (i=0; i<list.size(); i++) { mAppList.add(list.get(i).loadLabel(pm).toString()); handler.sendEmptyMessage(MSG_UPDATE_LIST); } // 關閉正在處理視窗 dialog.dismiss(); } }; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub switch (msg.what) { case MSG_UPDATE_LIST: // 更新應用程式列表 mApps.setAdapter(new ArrayAdapter(mContext, android.R.layout.simple_list_item_1, mAppList)); break; } super.handleMessage(msg); } }; }
後面發現有效率更高的方法,其實不用每次更新一項都需要構建一個Adapter的,,,
把Adapter和一個List<?>綁定在一起之後,可以直接改變List<?>的內容,然後再使用Adapter的資料集更新通知,即可改變ListView的內容,所以後面改了一下源碼變成這個樣子:
package com.Yao_GUET.test; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; /** * @author Yao.GUET * blog: http://blog.csdn.net/Yao_GUET * 實現動態載入一個ListView */ public class ProcessorBarTest extends Activity { public static final int MSG_UPDATE_LIST = 18; private ListView mApps; private Context mContext; private List<String> mAppList; private ProgressDialog dialog; private ArrayAdapter mAdapter; private boolean mIsLoaded = false; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.processorbar_test); // ListView 列表 mApps mApps = (ListView)findViewById(R.id.lvProcessbar); mContext = this; mAppList = new ArrayList<String>(); mAdapter = new ArrayAdapter(mContext, android.R.layout.simple_list_item_1, mAppList); mApps.setAdapter(mAdapter); // 設定正在處理視窗 dialog = new ProgressDialog(mContext); dialog.setIcon(R.drawable.icon); dialog.setTitle("ProgressDialog"); dialog.setMessage("Please wait while loading application list..."); dialog.setCancelable(false); dialog.show(); // 開始動態載入線程 mThreadLoadApps.start(); mApps.setOnItemClickListener(new AdapterView.OnItemClickListener(){ public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // TODO Auto-generated method stub mAppList.remove(position); mAdapter.notifyDataSetChanged(); } }); // 擷取已經安裝程式列表 PackageManager pm = mContext.getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); // 逐項添加程式,並發送訊息更新ListView列表。 for (int i=0; i<list.size(); i++) { mAppList.add(list.get(i).loadLabel(pm).toString()); mAdapter.notifyDataSetChanged(); } mIsLoaded = true; } private Thread mThreadLoadApps = new Thread(){ @Override public void run() { int i = 0; // TODO Auto-generated method stub while (!mIsLoaded) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } // 關閉正在處理視窗 dialog.dismiss(); } }; }