论__AlertDialog自定义布局回调修改的正确方式

简介:

论__AlertDialog自定义布局回调修改的正确方式


本文由 Luzhuo 编写,请尊重个人劳动成果,转发请保留该信息.
原文: http://blog.csdn.net/Rozol/article/details/50441057
微博: http://weibo.com/u/2524456400


这几天写了个应用,自定义了AlertDialog布局,加入了TextView和进度条展示,但是不管怎么调,Dialog就是不显示出来,即时显示出来也不更新,只在程序执行完了才更新.
于是没辙了,换成Android自带的ProgressDialog试试,结果还是老样子.(也是要么不显示,即时显示了也不更新,只在程序执行完了才更新.)
于是亲自动手写个Demo看看到底是什么问题.(反复折腾,终于折腾出结果来了,先下结论吧.)
这篇文章没有插图,下面有Github的链接,下载里面的apk就能很清楚的知道这篇文章在讲什么啦!!!

结论

  • 一定要在辅助线程里执行的回调才能修改Dialog的界面; (第1,2的案例)
  • 在ui线程里执行的回调不能修改Dialog的界面.(准确的说:能修改,但是不是你想要的效果) (第3,4的案例)

详细分析

先看MainActivity里的代码:

public class MainActivity extends Activity implements OnClickListener {
    // ... 省略
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case Start:
                dialog.show();// 显示
                Log.i(TAG, "start");
                break;
            case Back:
                textview.setText((String)msg.obj);
                Log.i(TAG, (String)msg.obj);
                break;
            case End:
                dialog.dismiss();
                Log.i(TAG, "end");
                break;
            }
        }
    };
    // ... 省略
    private void initData() {
        dialog_view = View.inflate(this, R.layout.dialog, null);
        textview = (TextView) dialog_view.findViewById(R.id.textview);
        // AlertDialog
        AlertDialog.Builder builder = new Builder(this);
        builder.setCancelable(false);
        dialog = builder.create();
        dialog.setView(dialog_view, 0, 0, 0, 0);
    }

    private void threadStart() {
        DialogThread dialogThread = new DialogThread();
        dialogThread.setOnBackListener(new OnBack() {
            @Override
            public void onStart() {
                Message msg = Message.obtain();
                msg.what = Start;
                handler.sendEmptyMessage(Start);
            }
            @Override
            public void onBack(String backName) {
                Message msg = Message.obtain();
                msg.what = Back;
                msg.obj = backName;
                handler.sendMessage(msg);
            }
            @Override
            public void onEnd() {
                Message msg = Message.obtain();
                msg.what = End;
                handler.sendEmptyMessage(End);
            }
        });
        dialogThread.start();
    }

从上诉代码可以看出,我是让 子线程/异步任务/ui线程 里执行的任务通过回调方式.
然后在回调里发送Message的方式更新ui.
由于 子线程/异步任务 都不能修改ui,所以使用发送Message的方法,但是ui线程是可以直接修改Dialog里的布局的,所以我会增加一个通过回调直接修改Dialog的案例.

1.子线程里回调,修改dialog界面

第一种,通过开启子线程方式,然后回调修改dialog的界面.
由于子线程不能修改ui界面,所以使用handler方式.

public class DialogThread {
    // ... 省略
    public void start(){
        new Thread(){
            public void run() {
                if(onBack != null) onBack.onStart();
                while(x<10){
                    if(onBack != null) onBack.onBack(String.valueOf(x));
                    SystemClock.sleep(1000);
                    x++;
                }
                if(onBack != null) onBack.onEnd();
            };
        }.start();
    }
// ... 省略
}

子线程通过执行回调,回调里发送Message修改Dialog的界面.
执行的结果是可行的,完全可以修改Dialog的显示.效果非常好.

2.异步任务里回调,修改dialog界面

第二种,通过异步任务方式,然后回调修改dialog的界面.
由于辅助线程不能修改ui界面,所以使用handler方式.

public class DialogAsync extends AsyncTask<Context, Void, Void> {
    // ... 省略
    @Override
    protected Void doInBackground(Context... params) {
        if(onBack != null) onBack.onStart();
        while(x<10){
            if(onBack != null) onBack.onBack(String.valueOf(x));
            SystemClock.sleep(1000);
            x++;
        }
        if(onBack != null) onBack.onEnd();
        return null;
    }
// ... 省略
}

异步任务通过执行回调,回调里发送Message修改Dialog的界面.
执行的结果是可行的,完全可以修改Dialog的显示.效果非常好.

3.UI线程里回调,修改dialog界面

第三种,通过ui线程方式,然后回调修改dialog的界面.
由于为了与上面的例子做个参照物,所以还是使用handler方式.

public class DialogThread {
    // ... 省略
    public void start(){
        new Thread(){
            public void run() {
                if(onBack != null) onBack.onStart();
                while(x<10){
                    if(onBack != null) onBack.onBack(String.valueOf(x));
                    SystemClock.sleep(1000);
                    x++;
                }
                if(onBack != null) onBack.onEnd();
            };
        }.start();
    }
// ... 省略
}

ui线程通过执行回调,回调里发送Message修改Dialog的界面.
执行的结果是糟糕的,Log在程序执行完后才打印,而且是一起快速打印,而且根本没看到Dialog的显示.

4.UI线程里回调,修改dialog界面

第四种,通过ui线程方式,然后回调修改dialog的界面.
由于为了与第三个例子做个参照物,所以直接回调然后修改Dialog的方式.
由于还是执行第三个例子的DialogThread类的方法,代码这里不再粘贴.
这里粘贴MainActivity里的部分主要代码.

public class MainActivity extends Activity implements OnClickListener {
    // ... 省略
    private void mainStart1() {
        DialogMain dialogMain = new DialogMain();
        dialogMain.setOnBackListener(new OnBack() {
            @Override
            public void onStart() {
                dialog.show();// 显示
                Log.i(TAG, "start");
            }
            @Override
            public void onBack(String backName) {
                textview.setText(backName);
                Log.i(TAG, backName);
            }
            @Override
            public void onEnd() {
                dialog.dismiss();
                Log.i(TAG, "end");
            }
        });
        dialogMain.start();
    }
}

ui线程通过执行回调,回调里直接修改Dialog的界面.
执行的结果是糟糕的,Log能完美的打印,但是根本没看到Dialog的显示.

  • Q:如何知道当前线程是否是ui线程?
  • A:Log.i(“UIThread”, “当前线程”.concat(Thread.currentThread().getId() == 1 ? “是” : “不是”).concat(“UI线程”));

Github

GithubDemo代码

目录
相关文章
|
机器学习/深度学习 消息中间件 算法
如何设计数据中台
如何设计数据中台
858 0
怎样将Beyond Compare添加到系统右键菜单
怎样将Beyond Compare添加到系统右键菜单
2092 0
|
存储 编解码 监控
【软件设计师备考 专题 】音频和视频信息的应用
【软件设计师备考 专题 】音频和视频信息的应用
288 0
|
Oracle Java 关系型数据库
try-catch必须放在循环体外吗
try-catch必须放在循环体外吗
|
存储 弹性计算 安全
《阿里云认证的解析与实战-云计算ACP认证》——云计算ACP训练营第2天——一、弹性块存储EBS
《阿里云认证的解析与实战-云计算ACP认证》——云计算ACP训练营第2天——一、弹性块存储EBS
|
C++
c++面向对象基础教程————派生类中的析构函数和构造函数(二)
c++面向对象基础教程————派生类中的析构函数和构造函数(二)
317 0
c++面向对象基础教程————派生类中的析构函数和构造函数(二)
|
安全 Shell 网络安全
[永久开源] vulntarget-b_打靶记录(下)
[永久开源] vulntarget-b_打靶记录
399 0
|
算法 Java Go
详解gc(垃圾回收)机制二:认识GC基本概念
详解gc(垃圾回收)机制二:认识GC基本概念
266 0
详解gc(垃圾回收)机制二:认识GC基本概念
|
SQL 存储 Oracle
【B站老杜】mysql详解(中)
【B站老杜】mysql详解
191 0
|
监控 Linux
报名 | 阿里云APM城市技术行 · 深圳站
时间:2018年10月27日(周六) 地点:深圳 · 空体新媒体实验室 活动主题:应用全链路性能和诊断最佳实践 活动收益:您将和阿里巴巴APM专家面对面,了解阿里在应用全链路性能和诊断方面踩过的坑和学过的课,更有《企业IT架构转型之道》和淘宝公仔送出 活动详情和报名方式如下:
1727 0