cari

Rumah  >  Soal Jawab  >  teks badan

thread - Android 主线程更新UI问题

本人使用了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();
                    }
                });
    }
天蓬老师天蓬老师2771 hari yang lalu1294

membalas semua(3)saya akan balas

  • PHP中文网

    PHP中文网2017-04-18 09:15:26

    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();
                            }
                        });
                        
             }
             
         }               
                        
            
    

    balas
    0
  • ringa_lee

    ringa_lee2017-04-18 09:15:26

    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;
        }

    balas
    0
  • ringa_lee

    ringa_lee2017-04-18 09:15:26

    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就好了
            }
        })

    balas
    0
  • Batalbalas