thread - Android 主线程更新UI问题
天蓬老师
天蓬老师 2017-04-18 09:13:26
0
3
1290

本人使用了OKGO的框架, 下载文件,在下载之前创建一个 等待框,在更新进度的回调中,更新等待框的百分比, 可是爆了如下错误!

通过LOG 发现 UI线程ID 不一样

是什么问题? 求大神解决,以下是源码~!

public void setDownloadUrl(String url) {
        if (TextUtils.isEmpty(url))
            return;

        if (dialog == null) {
            dialog = new ProgressDialog(mainViewImpl.getContext());
            dialog.setCancelable(false);
            dialog.setCanceledOnTouchOutside(false);
            dialog.setMessage("正在下载文件...");
            dialog.setMax(100);
            dialog.setTitle("软件更新");
        }
        dialog.show();

        L.i("(外)线程ID: " + Thread.currentThread().getId());

        OkGo.get(url)//
                .tag(this)//
                .execute(new FileCallback() {  //文件下载时,可以指定下载的文件目录和文件名
                    @Override
                    public void onSuccess(File file, Call call, Response response) {
                        // file 即为文件数据,文件保存在指定目录
                        L.i("成功: ");
                        if (dialog != null && dialog.isShowing())
                            dialog.dismiss();
                        startUpdate(file);
                    }

                    @Override
                    public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
                        //这里回调下载进度(该回调在主线程,可以直接更新ui)
                        L.i("(内)线程ID: " + Thread.currentThread().getId());
                        dialog.setMessage("正在下载文件......" + (int) (progress * 100) + "%");
                    }

                    @Override
                    public void onError(Call call, Response response, Exception e) {
                        super.onError(call, response, e);
                        L.i("失败: ");
                        if (dialog != null && dialog.isShowing())
                            dialog.dismiss();
                    }
                });
    }
天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

membalas semua(3)
洪涛

Anda menggunakan seni bina MVP Anda tidak seharusnya mengendalikan kawalan dalam Paparan dalam Penyampai, tetapi anda mengendalikan kawalan Dialog dalam Penyampai.
Jadi pendekatan yang betul hendaklah seperti berikut:

Interface View{

    void showDialog();
    void updateDialog(int count);
    void dismissDialog();
    void showError();
    void dismissError();
    
    }
    
    class Presenter{
      View  view;
      public Presenter(View view){
      this.view=view;
      }
    
      public void setDownloadUrl(String url){
            OkGo.get(url)//
                    .tag(this)//
                    .execute(new FileCallback() {  //文件下载时,可以指定下载的文件目录和文件名
                        @Override
                        public void onSuccess(File file, Call call, Response response) {
                            // file 即为文件数据,文件保存在指定目录
                            view.dismissDialog();
                        }
    
                        @Override
                        public void downloadProgress(long currentSize, long totalSize, float progress, long networkSpeed) {
                            view.update((int)progress);
                        }
    
                        @Override
                        public void onError(Call call, Response response, Exception e) {
                            super.onError(call, response, e);
                            view.dismissDialog();
                            view.showError();
                        }
                    });
                    
         }
         
     }               
                    
        
左手右手慢动作

Anda telah mencetak bahawa persekitaran di mana kaedah downloadProgress() dilaksanakan bukan UI线程, kemudian anda meletakkan

dialog.setMessage("正在下载文件......" + (int) (progress * 100) + "%");
Hanya letakkan pelaksanaan

pada urutan UI.

runOnUiThread(new Runnable() {
            @Override
            public void run() {
                dialog.setMessage("正在下载文件......" + (int) (progress * 100) + "%");
            }
        });

||-----------------------Suplemen----- - -----||

Saya baru sahaja mencetak log, dalam utas ui dan sub-utas:

03-03 15:20:54.592 30842-30842/com.didikee.commondependence E/test: Out-->ThreadName: main  id: 1
03-03 15:20:54.592 30842-30891/com.didikee.commondependence E/test: Inner-->ThreadName: main  id: 807

Id utas utama ialah 1, id sub-utas ialah 807, kedua-dua nama mereka adalah utama, dan nama utas boleh ditentukan:

public Thread(String name) {
        //这是指定线程名称的构造函数
        init(null, null, name, 0);
    }

ID utas dijana secara dalaman dan tidak boleh dinyatakan secara manual, dengan kata lain, nama utas itu tidak meyakinkan . Mereka tidak sama dengan utas utama Jika id berbeza, maka yang berbeza bukanlah utas utama. Anda boleh melihat kod sumber Thread kelas:

tid = nextThreadID();
....
private static synchronized long nextThreadID() {
        return ++threadSeqNumber;
    }
左手右手慢动作

Pelaksanaan tugas muat turun dalam UIThread akan menyekat antara muka Untuk tidak menjejaskan pengalaman aplikasi, kami akan melaksanakan tugas muat turun dalam urutan tak segerak dan panggilan balik yang dilaksanakan dalam utas tak segerak secara semula jadi dalam urutan tak segerak.
Mekanisme komunikasi benang yang paling biasa digunakan dalam Android ialah Pengendali:

    Handler mHandler = new Handler(Looper.getMyLooper());
    handler.post(new Runnable(){
        @Override
        void run(){
        //在这里更新ui就好了
        }
    })
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan