【问题标题】:Android: how to resume main thread after download is finishedAndroid:下载完成后如何恢复主线程
【发布时间】:2012-11-08 14:03:12
【问题描述】:

如果我在任何 Activity 中,我想下载一个文件(使用线程),同时我希望主线程等待下载完成,我该怎么办?

【问题讨论】:

    标签: android multithreading android-activity resume


    【解决方案1】:

    从活动中使用AsyncTask..

    new DownloadTask(this).execute();
    

    任务举例:

    public class DownloadTask extends AsyncTask<Void, Void, String>  {
    
    private ProgressDialog progressDialog;  
    private Context context;
    
    /**
     * 
     * @param context
     * @param pdfDoc the document of the PDF
     */
    public DownloadTask(Context context) {
        this.context = context;
    
        progressDialog = new ProgressDialog(context);
    }
    
    @Override
    protected void onPreExecute() {  
            progressDialog.setMessage("Downloading...");
            progressDialog.setIndeterminate(true);
            progressDialog.show();
    }
    
    @Override
    protected String doInBackground(Void... arg0) {
        //download here
    }
    
    @Override
    protected void onPostExecute(final String result) {
            progressDialog.dismiss();
    
    }
    }
    

    【讨论】:

    • 进一步补充,您的主线程在等待时不应完全锁定。假设用户将在 Activity 上玩其他元素,甚至在下载完成之前终止它。使用上面的示例 Async 就可以做到这一点。
    • 我无法在下载之前创建我的活动。
    【解决方案2】:

    使用 AsyncTask 和回调。

    public interface DownloadCallback<T>{
        public void onFinishDownload(T downloadedResult);
    }
    
    
    public static void downloadString(String url, DownloadCallback<String> callback){
        new AsyncTask<Void,Void,Void>(){
    
            String result;            
    
            @Override
            protected void onPreExecute() {  
                // Do things before downloading on UI Thread
            }
    
            @Override
            protected String doInBackground(Void... arg0) {
    
                 //download here
                 result = download(url);
    
            }
    
            @Override
            protected void onPostExecute(final Void result) {
                // Do things on UI thread after downloading, then execute your callback
                if (callback != null) callback.onFinishDownloading(result);
            }
    
    
        }.execute();
    }
    

    要使用它,您只需这样做:

    downloadString("http://www.route.to.your.string.com", new DownloadCallback<String>(){
        public void onFinishDownloading(String downloadedResult){
             Toast.makeText(YourActivityName.this, downloadedResult, Toast.LENGTH_SHORT).show();
        }
    });
    

    【讨论】:

    • 使用这种方法,您甚至可以在其他下载任务中将回调重用于其他结果类型;-)
    • 这样:A) 主线程执行onPreExecute,然后休眠。 B) 新线程执行 doInBackground。同时主线程没有阻塞,你可以做任何你想做的事情。 C) 主线程唤醒并执行 onPostExecute。
    【解决方案3】:

    如果您希望线程与主线程通信,告知下载完成,请使用handler 此代码将帮助您理解它

    MyHnadler handler;
    onCreate(Bundle savedInstance)
    {
     setContent..
    ...
     handler=new MyHandler();
     new MyThread().start();
    }
    public class MyHandler extends Handler
    {
      @Override
      public void handleMessage(Message message) {
                switch (message.what) {
                case 1:   //....threading over
                             //write your code here
                       break;
                case2 : //if you want to be notiifed of something else
                       ..
     }
    
    public class MyThread extends Thread
    {
     @Override
     public void run()
     {
       //run the threa
       //and when over
       Message msg=handler.getMessage();
       msg.what=1;
       handler.sendMessage(msg);   //send the message to handler
     }
    }
    } 
    


    如您所见,线程通过 Handler 与 UI 线程通信。在上面的示例中,我只将线程中的任何对象发送到 UI 线程。为此,只需在线程中执行msg.obj=your_obj。它可以是任何对象。希望这对你有帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多