【问题标题】:public AsyncTask to be called from several classes从多个类调用的公共 AsyncTask
【发布时间】:2014-07-15 01:34:11
【问题描述】:

我是 Android 新手。自从我开始从事这个项目以来已经有几个星期了。阅读代码已经让我看到很多私有异步任务基本相同(调用 API)所以我想知道是否有更好的解决方案,我的想法是创建一个名为 ApiCaller 的公共异步任务,它将返回一个 JSONObject 和负责解析 JSON 的是调用 ApiCaller 的类:

public class ApiCaller extends AsyncTask<String, String, JSONObject> {
    private static final String TAG = "ApiCall";
    private final String apiVersion = "v1";
    private final String baseURL = "http://my.api.com/";
    private String URL = null;

    /**
     * Generates the URL to call the API.
     *
     * @param params List with the params to call the API.
     */
    public ApiCaller(ArrayList<NameValuePair> params){
        String apiURL = this.baseURL + this.apiVersion + "/?";
        String paramsList = URLEncodedUtils.format(params, "utf-8");
        this.URL = apiURL + paramsList;
    }

    @Override
    protected JSONObject doInBackground(String ... params) {
        Log.i(TAG, "API:");
        Log.i(TAG, this.URL);
        JSONManager jParser = new JSONManager();
        JSONObject jsonObject = jParser.getJSONFromUrl(this.URL);
        return jsonObject;
}

有没有办法在类之外返回 JSONObject,这样我就可以执行以下操作:

JSONObject js = apiCaller.execute();

或者任何其他解决方案可以避免在每次我需要调用 API 时创建新的异步任务?使用我当前的代码,我无法得到它,但我不知道缺少什么?也许在 onPostExecute 中返回它?

【问题讨论】:

    标签: java android architecture android-asynctask


    【解决方案1】:

    前段时间我问过一个类似的问题

    One AsyncTask for multiple Activities

    我找到的解决方案在另一个问题中得到了回答:

    Common class for AsyncTask in Android?

    基本上,您需要的是interface

    我将解释基础知识,尽管您应该查看@SirDarius 的原始答案。

    你可以创建一个这样的界面:

    interface AsyncTaskCompleteListener<T> {
       public void onTaskComplete(T result);
    }
    

    并在您需要使用AsynTask 的所有类中实现该接口,然后,在您的通用Asynstask 中,您需要有一个回调AsyncTaskCompleteListener 并从您的onPostExecute 调用它

    class B implements AsyncTaskCompleteListener<JSONObject> {
    
        public void onTaskComplete(JSONObject result) {
            // do whatever you need
        }
    
        public void launchTask(String url) {
            ApiCaller a = new ApiCaller(context, ArrayList<NameValuePair> params, this);
            ApiCaller.execute(url);
        }
    }
    
    
    class ApiCaller extends AsyncTask<String, Void, String> {
        private AsyncTaskCompleteListener<String> callback;
    
        public ApiCaller(Context context, ArrayList<NameValuePair> params, AsyncTaskCompleteListener<String> cb) {
            this.context = context;
            this.callback = cb;
        }
    
        protected void onPostExecute(String result) {
           finalResult = result;
           progressDialog.dismiss();
           System.out.println("on Post execute called");
           callback.onTaskComplete(result);
       }  
    }
    

    【讨论】:

    • 你已经有了在UI线程上调用的onPostExecute(),它的参数是泛型的,再给它加一个接口也没用了。
    • 他想要的是将一个从许多活动中调用的Asyntask概括为一个。检查stackoverflow.com/questions/3291490/… 有接口是有意义的
    • 但是有没有办法从那里得到它?据我所知 onPostExecute 没有返回任何东西
    • 它不返回任何内容,但是因为您的调用将实现接口,所以您必须在该类中有一个方法public void onTaskComplete(T result),您将在其中接收结果。我已经用一个例子更新了我的答案。
    • 当然 onPostExecutes 返回一些东西,即与您的接口完全相同的值,以与接口相同的方式作为回调。所以是的,您可以向 AsyncTask 添加一个接口,或者您覆盖 onPostExecute ...但两者都...为什么?
    【解决方案2】:

    因为异步的AsyncTask不能调用方法并获取返回值;

    您可以在您的内联代码上使用 AsyncTask 并执行 postExecute 您的 JSON 对象:

       new AsyncTask<String, String, JSONObject>(){
            @Override
            protected Void doInBackground(String... params) {
    
                //...
            }
            @Override
            protected void onPostExecute(JSONObject result) {
    
                // ...
            }
        }.execute(...);
    

    【讨论】:

      【解决方案3】:

      您应该实现一个将传递给异步任务的侦听器。当 asynctask 完成时,它会调用 listener 的方法:

      首先,在一个新的java文件中创建一个监听器:

      public interface onTaskDoneListener{
          void onTaskDone(JSONObject result);
      }
      

      将它传递给您的 AsyncTask:

      private onTaskDoneListner donelistner;
      
      public ApiCaller(ArrayList<NameValuePair> params,onTaskDoneListener donelistener){
          String apiURL = this.baseURL + this.apiVersion + "/?";
          String paramsList = URLEncodedUtils.format(params, "utf-8");
          this.URL = apiURL + paramsList;
      this.donelistener = donelistener;
      }
      

      然后,在 AsyncTask 的 onPostExecute 方法中

      this.donelistener.onTaskDone(result)
      

      用法:

      new ApiCaller(params,new onTaskDoneListener() {
              @Override
              public void onTaskDone(JSONObject result) {
                         //This will be called when the asynctask finishes
      
                         //Do something with the result
      });
      

      【讨论】:

        【解决方案4】:

        第 1 步:定义接口。

        public interface WebServiceListener {
        
                public void onLoginActionComplete (ArrayList<String> arrayList);
        }
        

        第 2 步:在您的活动类中实现 WebServiceListener。

        public class LoginActivity extends Activity implements  WebServiceListener  {
        
        @Override
                public void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        setContentView(R.layout.login);
        
           /* Calling the AsyncTask here,you could call in Login Button Click...   */
        
                  WebServiceClient httpclient = new WebServiceClient(this);
                                httpclient.execute(ssoURLStr);
        
        }
        
        
        
                @Override
                public void onLoginActionComplete  (ArrayList<String> arrayList) {
                        // TODO Auto-generated method stub
        
                 /*      Read the response     */
                      String Response = arrayList.get(0);
        
        
                }
        
        
        }
        

        第 3 步:此处为您的 AsynTask 类代码。

        public class WebServiceClient extends
                        AsyncTask<String, Integer, ArrayList<String>> {
        
         WebServiceListener listener = null;
        
        /*  Constructor added  WebServiceListener here         */
        public WebServiceClient ( WebServiceListener listener)
        {
          this.listener  =  listener;
        }
        
        
        @Override
                protected ArrayList<String> doInBackground(String... params) {
                        // TODO Auto-generated method stub
        
                       ArrayList<String> arrayList = null;
        
                    " write  your  http code here and get the response and update the    
                    arrayList <String> here"
        
                        return arrayList;
                }
        
        
        @Override
                protected void onPostExecute(ArrayList<String> arrayList) {
                        // Returns the contents of the HTML page
        
                              listener.onLoginActionComplete (arrayList);
         }
        
        
        }
        

        我也问过这个question。也许这个link 会有所帮助

        【讨论】:

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