【问题标题】:AsyncTask with REST API带有 REST API 的 AsyncTask
【发布时间】:2017-10-21 11:11:57
【问题描述】:

我有一个使用 REST API 填充列表的 Android 应用。

我正在尝试使用 AsyncTask 获取 API,但我无法理解它的工作原理。我在后台创建 API 对象以避免 NetworkOnMainThreadError,但这会导致我的 createItems() 方法在空对象上被调用。

如何在后台创建 API 对象并在 OnCreate 期间仍然可以使用它?谢谢!

这是我的 OnCreate() 方法的一部分:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawer);

        createLists();
        populateNameLists();
        new GetAPITask().execute();
        createItems();

(...)
    }

这是导致错误的方法(createItems()):

public void createItems() {
        testString = api.testSession();
        itemString = api.getItems(...);
(...)
    }

这里是异步任务:

private class GetAPITask extends AsyncTask<String, Integer, String> {

        protected void onPreExecute() {
            super.onPreExecute();
        }

        protected String doInBackground(String... params) {

            api = new API(getString(R.string.dev_id), getString(R.string.auth_key));

            return "API Created";
        }

        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        protected void onPostExecute(String result) {
            super.onPostExecute(result);
        }
    }

【问题讨论】:

    标签: android rest android-activity android-asynctask networkonmainthread


    【解决方案1】:

    使用 AsyncTask 的目的是在后台获取数据,一旦获得数据,就可以使用它填充视图。仅当数据准备好使用时,您才运行您的方法来填充视图,这应该在 onPostExecute 中处理。你应该这样做:

    protected void onPostExecute(String result) {
            super.onPostExecute(result);
            createItems();
    }
    

    【讨论】:

      【解决方案2】:

      您的 ASyncTask 引用了外部类

      将签名改为

       private static class GetAPITask extends AsyncTask<String, Integer, String> {
      

      这将阻止您访问类中的代码和变量。

      这是您在 ASyncTask 之外访问 api 的方式 - 导致您的困惑

      更多解释在这里:https://stackoverflow.com/a/10540669/413127


      这意味着您无法访问 ASyncTask 之外的 api 变量(这是正确的)。然后,您必须将代码移动到后台线程中,并决定您的 ASyncTask 要返回什么。目前它返回一个String;

      您可以通过回调访问该字符串:

      private static class GetAPITask extends AsyncTask<String, Integer, String> {
      
              interface Callback {
                  void onComplete(String text);
              }
      
              private final API api;
              private final Callback callback;
      
              GetAPITask(API api, Callback callback) {
                  this.api = api;
                  this.callback = callback;
              }
      
              protected String doInBackground(String... params) {
                  return "API Created";
              }
      
              protected void onPostExecute(String result) {
                  super.onPostExecute(result);
                  callback.onComplete(result);
              }
          }
      

      然后像这样使用它:

      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_drawer);
      
          //createLists();
          //populateNameLists();
          API api = new API(getString(R.string.dev_id), getString(R.string.auth_key));
          new GetAPITask(api, new GetAPITask.Callback() {
                @Override
                public void onSuccess(String result) {
                       Log.d("TUT", "My asynctask returned: " + result);
                }
          }).execute();
          //createItems();
      
          (...)
      }
      

      如您所见,现在它已被清理干净,您的 ASyncTask 除了在 doInBackground() 方法中返回字符串外什么也没做。您需要将要执行的代码移到此处! (即将createItems 移动到doInBackground() 内)


      类似:

              protected String doInBackground(String... params) {
                  String testString = api.testSession();
                  String itemString = api.getItems(...);
                  (...)               
      
                  return testString;
              }
      
              protected void onPostExecute(String result) {
                  super.onPostExecute(result);
                  callback.onComplete(result);
              }
      

      如果你想从 ASyncTask 返回多个字符串,你必须创建一个数据类并返回它。

      【讨论】:

        猜你喜欢
        • 2013-01-14
        • 2012-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-01
        • 2021-04-20
        • 2015-10-19
        • 2014-08-07
        相关资源
        最近更新 更多