Android 數據儲存的方式之本地數據庫儲存

Android 數據儲存的方式有不少種 —— SharedPreferences 儲存  、 文件儲存 、 數據庫儲存 、 網絡儲存(儲存到後臺網絡) ,雖然儲存方式那麼多,可是這些儲存方式也有必定的規律可尋:java

SharedPreferences :  存儲 key value 鍵值對類型的簡單少許的簡單數據 (如用戶名 ,密碼 ,性別,年齡  。。。)android

文件 :  沒有固定規則的,大量的數據 (如:大量的圖片 ,文字 。。。)
數據庫

數據庫 : 有固定規則的,大量數據(如:學生的信息:ID 姓名 年齡 班級 。。。每一個學生都有的)
網絡

網絡 : 。。。多線程

今天這篇文章介紹的是數據儲存之數據庫儲存:參考文獻:http://blog.csdn.net/wu_wxc/article/details/49476779ide

先看下效果圖:函數

使用數據庫儲存數據有四個方法必需要知道的:增  刪  改  查
工具

咱們介紹下功能:既然是數據庫的儲存,功能無非就是增刪改查。佈局

1.添加黑名單是: 增。優化

2.刪除黑名單是: 刪。

3.長按條目顯示彈出框,修改黑名單的攔截方式:改。

4.整個列表的展現:查。

接下來看下代碼:

BlackNumDbHelper.java 繼承SQLiteOpenHelper

/**
 * 新建一個數據庫的類 db (database) 類要繼承squliteOpenhelper
 * 再建一個操做數據庫的工具類(增刪改查)
 * Created by Administrator on 2017/6/29.
 */
public class BlackNumDbHelper extends SQLiteOpenHelper {


    public BlackNumDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    /**
     * 第一次運行時,建立數據庫,調用此方法
     */
    public void onCreate(SQLiteDatabase db) {
                  //建表:自增加的主鍵 , 號碼 , 攔截模式
        db.execSQL("create table black_num(_id integer primary key autoincrement, number varchar(20) , mode integer);");

    }

    @Override
    /**
     * 當數據庫版本不同,升級數據庫時,調用此方法
     */
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

用一個操做數據庫的工具類 , 通常寫成單例模式:BlackDao .java

/**
 * BlackDao 操做咱們數據庫的工具類  咱們通常寫成單例模式
 * 單例模式 :  在整個應用程序中  無論什麼地方(類)  得到的都是同一個對象實例
 * @author Administrator
 */
public class BlackDao {

    //把數據庫建立出來
    private BlackNumDbHelper dbHelper;

    //black_num表名
    private String table_black_num ="black_num";

    //單例模式
    //不能讓每個類都能new一個  那樣就不是同一個對象了 因此首先構造函數要私有化    以上下文做爲參數
    private BlackDao(Context ctx){

        //因爲數據庫只須要調用一次,因此在單例中建出來
        dbHelper= new BlackNumDbHelper(ctx, "black_num.db", null, 1);
    }

    //public static 爲靜態類型  要調用就要有一個靜態的變量    爲私有的
    private static BlackDao instance;


    //既然BlackDao類是私有的  那麼別的類就不可以調用    那麼就要提供一個public static(公共的  共享的)的方法
    //方法名爲getInstance 參數爲上下文    返回值類型爲BlackDao
//要加上一個synchronized(同步的)
//若是同時有好多線程 同時去調用getInstance()方法  就可能會出現一些建立(new)多個BlackDao的現象  因此要加上synchronized
    public static synchronized BlackDao getInstance(Context ctx){

        //就能夠判斷  若是爲空 就建立一個, 若是不爲空就還用原來的  這樣整個應用程序中就只能獲的一個實例
        if(instance == null){
            instance = new BlackDao(ctx);

        }
        return  instance;
    }


    //經常使用方法  增刪改查

    /**
     * 添加黑名單  至數據庫
     * @param number
     * @param mode
     */
    public void addBlackNum(String number,int mode){

        //得到一個可寫的數據庫的一個引用
        SQLiteDatabase db = dbHelper.getWritableDatabase();

        ContentValues values= new ContentValues();
        values.put("number", number); // KEY 是列名,vlaue 是該列的值
        values.put("mode", mode);// KEY 是列名,vlaue 是該列的值

        // 參數一:表名,參數三,是插入的內容
        // 參數二:只要能保存 values中是有內容的,第二個參數能夠忽略
        db.insert(table_black_num, null, values);

    }

    /**
     * 刪除黑名單
     * @param number
     */
    public void deleteBlackNum(String number){
//		??dad?asd??sad?asdasdasd?
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        //表名  刪除的條件
        db.delete(table_black_num, "number = ?", new String[] {number});

    }

    /**
     * 更新黑名單攔截模式
     * @param number
     * @param newMode
     */
    public void updateBlackNumMode(String number,int newMode){
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values= new ContentValues();
        values.put("mode",newMode);

        db.update(table_black_num, values," number = ?", new String[]{number});
    }


    /**
     * //查找 每個黑名單都有 號碼和模式  先把號碼和模式封裝一個bean
     * 得到全部的黑名單
     * @return
     */
    //分頁查詢 修改

    public List<BlackNumBean> getBlackNumByPage(int pageIndex, int pageSize){
        //public List<BlackNumBean> getAllBlackNum(){
        //建立集合對象
        List<BlackNumBean> allBlackNum = new ArrayList<BlackNumBean>();

        SQLiteDatabase db = dbHelper.getReadableDatabase();
        //Cursor cursor = db.query(table_black_num, null, null, null, null, null, null);

        //分頁查詢  修改
        //Cursor cursor = db.rawQuery("select * from black_num limit "+pageSize+"offent"+(pageIndex * pageSize)+";", null);

        //order by _id desc 根據_id倒敘排列   使每次添加的黑名單在下次打開時顯示上面     同時每頁限制20個
        Cursor cursor = db.rawQuery("select * from black_num order by _id desc limit "+pageSize+" offset "+(pageIndex*pageSize)+";", null);
        // 返回的 cursor 默認是在第一行的上一行
        //遍歷
        while(cursor.moveToNext()){// cursor.moveToNext() 向下移動一行,若是有內容,返回true
            String number = cursor.getString(cursor.getColumnIndex("number"));// 得到number 這列的值
            //得到模式   一共三列   mode爲第二列
            int mode = cursor.getInt(2);

            //將number mode 封裝到bean中
            BlackNumBean bean = new BlackNumBean(number, mode);
            //封裝的對象添加到集合中
            allBlackNum.add(bean);
        }

        //關閉cursor
        cursor.close();
        SystemClock.sleep(1000);// 休眠2秒,模擬黑名單比較多,比較耗時的狀況
        return allBlackNum;

    };


    /**
     * 得到黑名單的數量
     */
    public int getBlackNumCount(){
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        Cursor cursor = db.query(table_black_num, new String[] {"count(*)"}, null, null, null, null, null);

        cursor.moveToNext();
        int count = cursor.getInt(0);// 僅查了一列,count(*) 這一刻列

        cursor.close();

        return count;

    }


/*	*//**
     * //查找 每個黑名單都有 號碼和模式  先把號碼和模式封裝一個bean
     * 得到全部的黑名單
     * @return
     *//*
		public List<BlackNumBean> getAllBlackNum(){
		//建立集合對象
		List<BlackNumBean> allBlackNum = new ArrayList<BlackNumBean>();

		SQLiteDatabase db = dbHelper.getReadableDatabase();
		Cursor cursor = db.query(table_black_num, null, null, null, null, null, null);

		// 返回的 cursor 默認是在第一行的上一行
			//遍歷
			while(cursor.moveToNext()){// cursor.moveToNext() 向下移動一行,若是有內容,返回true
				String number = cursor.getString(cursor.getColumnIndex("number"));// 得到number 這列的值
				//得到模式   一共三列   mode爲第二列
				int mode = cursor.getInt(2);

				//將number mode 封裝到bean中
				BlackNumBean bean = new BlackNumBean(number, mode);
				//封裝的對象添加到集合中
				allBlackNum.add(bean);
			}

			//關閉cursor
			cursor.close();


			SystemClock.sleep(1000);// 休眠2秒,模擬黑名單比較多,比較耗時的狀況

		return allBlackNum;

	};
	*/



    /**
     * 根據號碼,得到攔截模式
     * @param number
     * @return
     * 若是不是黑名單,那麼,返回 -1
     */
    public int getMOdeByNumber(String number) {

        int mode =  -1;
        //得到一個可讀的數據庫的一個引用
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        //查詢  表   列   條件
        Cursor cursor = db.query(table_black_num, null, "number = ?", new String []{number}, null, null, null);

        if( cursor.moveToNext()){// 若是查到了,移動成功
            mode = cursor.getInt(cursor.getColumnIndex("mode"));

        }

        cursor.close();
        return mode ;
    }
    
}

BlackNumBean.java

/**
 * Created by Administrator on 2017/6/29.
 */
public class BlackNumBean {
    public String number;
    public int mode;

    public BlackNumBean() {
        super();
        // TODO Auto-generated constructor stub
    }

    public BlackNumBean(String number, int mode) {
        super();
        this.number = number;
        this.mode = mode;
    }

    @Override
    public String toString() {
        return "BlackNumBean [number=" + number + ", mode=" + mode + "]";
    }
}

MainActivity.java

/**
 * 具備固定規則的大量的數據 能夠儲存在數據庫中    因此建庫  而後增刪改查
 * 能夠有三列  _id主鍵列     number號碼列   mode int 0所有攔截   1攔截電話    2攔截短信
 * 新建一個數據庫的類 db (database) 類要繼承squliteOpenhelper
 */
public class MainActivity extends AppCompatActivity {

    private ListView listView;
    private LinearLayout llLoading;
    private ProgressBar progressBar;
    private TextView tvDesc;

    private MyAdapter adapter;

    /**
     * 黑名單操做的工具類
     */
    private BlackDao blackDao;
    //黑名單的集合
    //private List<BlackNumBean> allBlackNum;
    private List<BlackNumBean> blackNums;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ctx = this;

        listView = (ListView) findViewById(R.id.li_listView);
        llLoading = (LinearLayout) findViewById(R.id.ll_loading);
        progressBar = (ProgressBar) findViewById(R.id.pb_progressBar);
        tvDesc = (TextView) findViewById(R.id.tv_desc);

        blackDao = BlackDao.getInstance(this);

        // 只有當onCraete 執行完了之後,頁面纔會顯示出來,
        // 在onCreate 方法中不能有耗時的操做,哪怕是 1 秒也不行,會嚴重影響用戶體驗,
        // 若是有耗時的操做(加載數據),必定要開子線程
        fillData();

        //添加監聽
        regListener();

    }


    //修改黑名單  當長按某一個條目時 彈出提個修改對話框

    //添加一個長按的監聽
    private void regListener() {
        // listView 添加條目長按的監聽
        listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

            @Override
            /**
             * 長按某個條目時,調用此方法 ,
             * 注意,返回  true
             */
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {

                showUpdataBlackNumDialog(position);

                return true;
            }
        });
    }

    /**
     * 顯示更新黑名單對話框
     *
     * @param position 長按的條目的下標
     */
    protected void showUpdataBlackNumDialog(int position) {
        //複製添加黑名單的code 修改

        //在java代碼中建立對話框
        AlertDialog.Builder adb = new AlertDialog.Builder(this);
        dialog = adb.create();

        //從集合中獲取封裝的對象
        final BlackNumBean blackNumBean = blackNums.get(position);
        //將佈局轉換爲view對
        View view = getLayoutInflater().inflate(R.layout.dialog_updata_blacknum, null);
        final TextView tvBlackNum = (TextView) view.findViewById(R.id.tv_black_number);
        //獲取電話號碼 並賦值
        tvBlackNum.setText("黑名單:" + blackNumBean.number);
        final CheckBox cbStopCall = (CheckBox) view.findViewById(R.id.cb_stop_call);
        final CheckBox cbStopSms = (CheckBox) view.findViewById(R.id.cb_stop_sms);

        //獲取模式  並初始化模式
        switch (blackNumBean.mode) {
            case 0:
                cbStopCall.setChecked(true);
                cbStopSms.setChecked(true);
                break;
            case 1:
                cbStopCall.setChecked(true);
                cbStopSms.setChecked(false);
                break;
            case 2:
                cbStopCall.setChecked(false);
                cbStopSms.setChecked(true);

                break;
        }

        Button btnCancel = (Button) view.findViewById(R.id.btn_cancel);
        Button btnOk = (Button) view.findViewById(R.id.btn_ok);

        //爲兩個按鈕 添加點擊事件
        //取消按鈕
        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();

            }
        });
        //點擊肯定按鈕
        btnOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //獲取輸入框號碼
                String number = tvBlackNum.getText().toString().trim();
                if (TextUtils.isEmpty(number)) {
                    MyUtils.showToast(ctx, "號碼不能爲空");
                    return;
                }
                //獲取模式
                int newMode = 0;// 初始化模式
                if (cbStopCall.isChecked() && cbStopSms.isChecked()) {
                    newMode = 0;

                } else if (cbStopCall.isChecked() && !cbStopSms.isChecked()) {
                    newMode = 1;
                } else if (!cbStopCall.isChecked() && cbStopSms.isChecked()) {
                    newMode = 2;
                } else {
                    MyUtils.showToast(ctx, "請選擇攔截模式");
                    return;
                }

                //更新黑名單
                blackDao.updateBlackNumMode(blackNumBean.number, newMode);

                //顯示至listview頁面
                blackNumBean.mode = newMode;  //修改數據
                adapter.notifyDataSetChanged();//刷新

                //關閉對話框
                dialog.dismiss();
            }
        });
        dialog.setView(view);
        dialog.show();

    }


    /**
     * 當手指在listview上滑動時
     */
    private void resListener() {
        //爲ListView設置一個滑動監聽
        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            /**
             * 當滑動狀態發生改變時
             */
            public void onScrollStateChanged(AbsListView view, int scrollState) {
//				OnScrollListener.SCROLL_STATE_IDLE;  //空閒狀態     idle空閒
//				OnScrollListener.SCROLL_STATE_FLING;// 快速滑東,  沒有觸摸  但在滑動
//				OnScrollListener.SCROLL_STATE_TOUCH_SCROLL; // 觸摸並滑動

                //在空閒的時候 判斷屏幕最後一個條目,是不是listvist 的最後一個條目, 若是是  說命該加載項更多的數據了
                if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
                    //得到可見的最後一個條目的下表
                    int lastVisiblePosition = listView.getLastVisiblePosition();

                    if (lastVisiblePosition == adapter.getCount() - 1) {// 看到最後一個條目了

                        if (pageIndex < totalPage - 1) {
                            //當前頁面的下標 加一
                            pageIndex++;
                            fillData();

                        } else {
                            MyUtils.showToast(ctx, "沒有數據了");

                        }
                    }
                }
            }

            @Override
            /**
             * 滑動時不斷調用此方法
             */
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            }
        });

    }


    private void fillData() {
        //當點擊上一頁 下一頁 是將加載狂顯示出來
        llLoading.setVisibility(View.VISIBLE);

        // 進入頁面後  加載數據(開子線程)  根據結果 顯示頁面
        new Thread() {
            public void run() {
                //當第一次加載後  會把數據設置給集合
                //當第二次加載後  會把數據追加在第一次後
                if (blackNums == null) {//第一次
                    //全部的黑名單的集合
                    //	allBlackNum = blackDao.getAllBlackNum();
                    blackNums = blackDao.getBlackNumByPage(pageIndex, pageSize);

                } else { ///加載更多  ,數據追加
                    blackNums.addAll(blackDao.getBlackNumByPage(pageIndex, pageSize));

                }

                //獲取黑名單的數量
                int totalcount = blackDao.getBlackNumCount();
                if (totalcount % pageSize == 0) {// 判斷是否能整除
                    totalPage = totalcount / pageSize;

                } else {
                    totalPage = totalcount / pageSize + 1;
                }

                //若是集的size 是0 則沒有黑名單  ,若是不是零 則有黑名單 則要展現出來、、
                //而子線程不能改變頁面   那麼就要發送handler信息

                //發送一個空的消息 數據獲取完了 能夠刷新頁面
                handler.sendEmptyMessage(FLUSH_UI);
            }

            ;
        }.start();
    }


    //黑名單數據加載的方式二   分批加載
    //生成變量
    /**
     * 當前頁面的下標
     */
    private int pageIndex = 0;
    /**
     * 每一頁的數量
     */
    private int pageSize = 20;
    /**
     * 總頁數
     */
    private int totalPage;

    protected Activity ctx;

    //刷新界面用的  當得到了數據後 就發送一個信息
    private final int FLUSH_UI = 100;

    private Handler handler = new Handler() {

        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case FLUSH_UI://子線程得到了數據,開始刷新頁面

                    // 沒有黑名單的狀況
                    if (blackNums.size() == 0) {// 沒有黑名單的狀況
                        progressBar.setVisibility(View.GONE);
                        tvDesc.setText("沒有黑名單,請添加幾個吧");

                    } else {
                        //  有黑名單,關閉加載框,listView 展現黑名單  就是爲Listview 設置Adapter
                        llLoading.setVisibility(View.GONE);

                        if (adapter == null) { //第一次加載
                            adapter = new MyAdapter();
                            listView.setAdapter(adapter);

                        } else {
                            //追加數據
                            adapter.notifyDataSetChanged();// 刷新listView 不然仍會從頭開始 顯示
                        }
                    }
                    break;
            }
        }

        ;
    };


    /**
     * listview 若是不優化可能出現的問題:
     * 一: getView 方法 大量調用,建立大量的對象,形成內存的浪費,甚至是 OOM 異常
     * 二:若是getview 方法執行的時間過長,超過 150 毫秒,用戶就會明顯的感受到卡頓現象
     *
     * @author Administrator
     *         <p/>
     *         優化的目標:建立儘量少的對象,執行getView的時間儘量短
     *         <p/>
     *         listview 優化一:複用convertView
     *         優化的結果:當convertView 不爲空時,再也不建立新的 view 對象,省略了
     *         getLayoutInflater().inflate(R.layout.list_item_black_num, null);
     *         而  inflate 是一個比較耗時的動做。
     *         <p/>
     *         listView 優化二:使用ViewHolder
     *         優化的結果:當convertView 不爲空時 ,經過 convertView 身上的揹包,得到他的子view 而後,爲子view賦值,
     *         從而,省略了 findViewById 這個方法
     */
    private class MyAdapter extends BaseAdapter {

        @Override
        /**
         * 告訴 listview 有多少個條目
         */
        public int getCount() {
            // TODO Auto-generated method stub
            return blackNums.size();
        }

        @Override
        public Object getItem(int position) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public long getItemId(int position) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        /**
         * 返回第一個條目對應的 view ,
         * 當某個 條目 將要顯示在屏幕上時,就會調用getView 方法 ,將該條目建立出來
         * @param position 條目的下標
         * 新建一個list_item_black_num.xml的條目佈局
         */
        public View getView(final int position, View convertView, ViewGroup parent) {
            // TODO Auto-generated method stub

            View view;
            ViewHolder vh;
            if (convertView == null) {

                view = getLayoutInflater().inflate(R.layout.list_item_black_num, null);
                //建立ViewHolder
                vh = new ViewHolder();
                // 找到  子 view
                TextView tvNum = (TextView) view.findViewById(R.id.tv_number_list_item);
                TextView tvMode = (TextView) view.findViewById(R.id.tv_mode_list_item);

                ImageView ivDelete = (ImageView) view.findViewById(R.id.iv_delete_list_item);
                // 將子view 打包
                vh.tvMode = tvMode;
                vh.tvNum = tvNum;

                vh.ivDelete = ivDelete;
                // 將揹包背在view的身上
                view.setTag(vh);

            } else {
                view = convertView;
                //取出揹包
                vh = (ViewHolder) convertView.getTag();
            }

            BlackNumBean blackNumBean = blackNums.get(position);
            //用取出的揹包賦值
            vh.tvNum.setText(blackNumBean.number);

            switch (blackNumBean.mode) {
                case 0:
                    vh.tvMode.setText("所有攔截");
                    break;
                case 1:
                    vh.tvMode.setText("攔截電話");
                    break;
                case 2:
                    vh.tvMode.setText("攔截短信");
                    break;
            }

            //刪除黑名單
//			爲ivdelete設置一個點擊事件
            vh.ivDelete.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    //從數據庫中刪除數據
                    blackDao.deleteBlackNum(blackNums.get(position).number);
                    //從集合中刪除數據
                    blackNums.remove(position);

                    //刷新頁面
                    notifyDataSetChanged();
                }
            });
            return view;
        }
    }

    //優化二   先聲明一個臨時的輔助類  而後有幾個子view  聲明幾個成員變量
    private static class ViewHolder {

        public ImageView ivDelete;
        TextView tvNum;
        TextView tvMode;
    }

    /**
     * 添加黑名單
     *
     * @param v
     */
    public void addBlackNum(View v) {
        // 展現天年黑名單的對話框
        showAddBlackNumDialog();

    }

    private AlertDialog dialog;

    private void showAddBlackNumDialog() {
        //在java代碼中建立對話框
        AlertDialog.Builder adb = new AlertDialog.Builder(this);
        dialog = adb.create();

        //將佈局轉換爲view對象
        View view = getLayoutInflater().inflate(R.layout.dialog_add_blacknum, null);

        final EditText etInputNum = (EditText) view.findViewById(R.id.et_input_number);
        final CheckBox cbStopCall = (CheckBox) view.findViewById(R.id.cb_stop_call);
        final CheckBox cbStopSms = (CheckBox) view.findViewById(R.id.cb_stop_sms);

        Button btnCancel = (Button) view.findViewById(R.id.btn_cancel);
        Button btnOk = (Button) view.findViewById(R.id.btn_ok);

        //爲兩個按鈕 添加點擊事件
        //取消按鈕
        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();

            }
        });
        //點擊肯定按鈕
        btnOk.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //獲取輸入框號碼
                String number = etInputNum.getText().toString().trim();
                if (TextUtils.isEmpty(number)) {
                    MyUtils.showToast(ctx, "號碼不能爲空");
                    return;
                }
                //先初始化mode
                int mode = 0;
                if (cbStopCall.isChecked() && cbStopSms.isChecked()) {
                    mode = 0;

                } else if (cbStopCall.isChecked() && !cbStopSms.isChecked()) {
                    mode = 1;
                } else if (!cbStopCall.isChecked() && cbStopSms.isChecked()) {
                    mode = 2;
                } else {
                    MyUtils.showToast(ctx, "請選擇攔截模式");
                    return;
                }

                //將黑名單信息插入數據庫
                blackDao.addBlackNum(number, mode);

                //顯示至listview頁面
                //加入集合
                blackNums.add(0, new BlackNumBean(number, mode));//要 將黑名單添加至集合的第一位

                //祖傳錯誤   當數據庫中沒有數據    會直接進入黑名單添加數據  可是adapter在這個時候並無建立   因此刷新的時候會顯示空指針異常
                //因此要先判斷adapter 是否爲空

                if (adapter == null) {
                    adapter = new MyAdapter();
                    //
                    listView.setAdapter(adapter);

                }
                llLoading.setVisibility(View.GONE);
                adapter.notifyDataSetChanged();//刷新

                //關閉對話框
                dialog.dismiss();

            }
        });
        dialog.setView(view);
        dialog.show();

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="mp.zyqj.zz.mobilephone.MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            style="@style/tv_title"
            android:text="黑名單攔截" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="addBlackNum"
            android:layout_alignParentRight="true"
            android:layout_margin="5dp"
            android:text="添加黑" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >

        <LinearLayout
            android:id="@+id/ll_loading"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="#6600ff00"
            android:gravity="center"
            android:orientation="vertical"
            android:padding="8dp" >

            <ProgressBar
                android:id="@+id/pb_progressBar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

            <TextView
                android:id="@+id/tv_desc"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="玩命加載中,請稍候..." />
        </LinearLayout>

        <ListView
            android:id="@+id/li_listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" >
        </ListView>
    </RelativeLayout>
</LinearLayout>

源碼:http://download.csdn.net/detail/lijinweii/9884809