【问题标题】:Android : Wait for a background task to finish in main threadAndroid:等待后台任务在主线程中完成
【发布时间】:2015-09-03 16:12:16
【问题描述】:

我目前正在创建一个 Android 应用,但遇到了一个问题,我还没有解决。

我使用 Retrofit 库向服务器发送请求,根据 Retrofit 库,它是在后台线程中完成的。

我在主线程中调用了这个改造请求,我想等待这个后台线程完成以便处理它的输出。

我在论坛上发现了一个类似的问题,但我不知道如何实现: Android: how to wait AsyncTask to finish in MainThread?

我用Retrofit调用请求,请求完成后,Callback对象的success方法启动,但主线程仍在运行,到达后台前的最后一行任务已完成

如何强制我的主线程等待后台任务完成?

我的代码:

    // ... (main thread)
    // CALL TO THE SERVER

    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(LoginScreen.ENDPOINT).build();
    WebServices getFiles = restAdapter.create(WebServices.class);

    Callback<Response> callback = new Callback<Response>() 
    {
        @Override
        public void success(Response s, Response response) 
        {
            fileAvailable = new String(((TypedByteArray) s.getBody()).getBytes());
            //THIS IS EXECUTED WHEN THE BACKGROUND TASK IS FINISHED
        }

        @Override
        public void failure(RetrofitError retrofitError) 
        {
            Log.e(TAG, retrofitError.toString());
        }
    };
    getFiles.getFiles(id, callback);

    // I want here to work with fileAvailable, but the code
    // reaches this line before the background task is over.

我尝试像上一个链接一样创建一个Handler对象,并在success方法中调用sendEmptyMessage,但是没有成功。

如果有人可以帮助我,我将非常感激。

提前谢谢你,

【问题讨论】:

  • 有一种方法可以强制您的主线程阻塞,但这不是一个好主意,Android 系统可能会杀死您的应用程序。您可以使用倒计时闩锁或等待/通知调用来执行此操作。

标签: java android multithreading android-asynctask


【解决方案1】:

你不想阻塞你的主线程,这就是这个库的重点。您需要重新考虑如何执行此操作,因为如果您阻塞主线程,UI 将挂起(无响应)并且用户会感到不安。想想你上一次使用应用程序时,所有东西都被锁定了几秒钟。如果你阻塞了主线程,就会发生这种情况。

相反,您应该在响应处理程序中继续您的逻辑,或者您可以从内部类调用外部类的函数(回调是内部类)。

RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(LoginScreen.ENDPOINT).build();
WebServices getFiles = restAdapter.create(WebServices.class);

Callback<Response> callback = new Callback<Response>() 
{
    @Override
    public void success(Response s, Response response) 
    {
        fileAvailable = new String(((TypedByteArray) s.getBody()).getBytes());
        doSomethingOnSuccess();
    }

    @Override
    public void failure(RetrofitError retrofitError) 
    {
        Log.e(TAG, retrofitError.toString());
    }
};

//this runs before success(), so show a spinner or something,
//eg:http://stackoverflow.com/questions/9157504/put-a-progressbar-on-actionbar

}

-- 更新(根据您关于有多个后台任务的评论- 如果您有 2 个或更多后台任务并行运行(意味着它们不依赖于彼此的输出)但您需要全部完成才能对它们执行任何操作,它可能看起来像这样:

public class MyActivity extends Activity {

  private Result result1 = null;
  private Result result2 = null;
  public void onCreate(Bundle savedState) {
    super.onCreate(savedState);   
    Callback<Response> callback1 = new Callback<Response>() {
      @Override
      public void success(Response s, Response response) 
      {
          result1 = new String(((TypedByteArray) s.getBody()).getBytes());
          checkComplete();
      }
      @Override
      public void failure(RetrofitError retrofitError) 
      {
          Log.e(TAG, retrofitError.toString());
      }
    };

    Callback<Response> callback2 = new Callback<Response>() {
      @Override
      public void success(Response s, Response response) 
      {
          result2 = new String(((TypedByteArray) s.getBody()).getBytes());
          checkComplete();
      }
      @Override
      public void failure(RetrofitError retrofitError) 
      {
          Log.e(TAG, retrofitError.toString());
      }
    };
    getFiles.getFiles(id, callback1);
    otherthing.doSomething(id, callback2);
  }

  private void checkComplete() {
    if (result1 != null && result2 != null) {
        doSomethingWithResults();
    }
  }

  private void doSomethingWithResults() {
     //update UI
  }

}

【讨论】:

  • 非常感谢您的回答,但如果我必须等待其中两个后台任务完成才能在屏幕上显示任何内容。如何设置标志之类的东西以确保所有查询都已完成?
  • 两个后台任务是否相互依赖?意思是,您是否必须等待 1 完成才能执行另一个?如果是这样,您只需将它们链接起来(当另一个完成时调用一个)。如果它们同时运行,那么我建议在每个回调中将数据的结果设置为一个类变量,然后调用一个函数来测试两个结果是否完整,如果是,那么你可以继续。
【解决方案2】:

主线程没有“最后一行”,它正在进行中。 onCreate() 执行完成后主线程未完成。只需将要在数据上执行的代码放入成功处理程序中

//THIS IS EXECUTED WHEN THE BACKGROUND TASK IS FINISHED

是。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 1970-01-01
    • 2019-10-24
    • 2017-05-15
    相关资源
    最近更新 更多