【问题标题】:Getting results from several AsyncTasks从多个 AsyncTask 中获取结果
【发布时间】:2013-03-25 13:39:03
【问题描述】:

您好,感谢您的帮助。

我有一个method,它调用AsyncTask 来从网上检索一些数据。

method被依次调用多次,因此启动了多个 AsyncTasks

method 的每次启动中,我需要从相关的 AsyncTask (而不是从之前或之后调用的其他 AsyncTask)中获取正确的结果。

非常感谢任何帮助。


编辑编辑编辑编辑 添加了其余代码。

请注意:整个过程在Service中运行。

public static class UpdateService extends Service {
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        int[] appWidgetIds = intent.getIntArrayExtra("widgetsids");
        final int N = appWidgetIds.length;
        AppWidgetManager manager = AppWidgetManager.getInstance(this);
        for (int i = 0; i < N; i++) {
            int appWidgetId = appWidgetIds[i];
            Log.e("","i="+Integer.toString(i)+ " di "+Integer.toString(N));
            RemoteViews view = buildUpdate(getApplicationContext(),
                    appWidgetIds);
            manager.updateAppWidget(appWidgetId, view);
        }
        return (START_NOT_STICKY);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

private static  RemoteViews buildUpdate(Context ctxt, int[] appWidgetIds) {
    RemoteViews updateViews = new RemoteViews(ctxt.getPackageName(),
            R.layout.widget);
        updateViews.setTextViewText(R.id.price1, getPrice(list.get(0)
            .getSymbol()));

 }        
    //THIS METHOD IS CALLED SEVERAL TIMES IN SEQUENCE    <----
    private static String getPrice(String symbol) {
    String result="";
    UpdateTaskPrice up = new UpdateTaskPrice();
    up.execute(symbol, null, null);
    //HERE I WANT THE RESULT FROM onPostExecute()    <----
    return result;
}

//THIS IS THE ASYNCTASK WHICH IS LAUNCHED SEVERAL TIMES
public class UpdateTaskPrice extends AsyncTask<String, Void, String> {

    @Override
    protected void onProgressUpdate(Void... progress) {
    }

    @Override
    protected void onPostExecute(String result) {
    //HERE I RECEIVE THE RESULT FROM doInBackground    <----
    //I NEED TO PASS IT BACK TO getPrice()    <----
    }

    @Override
    protected String doInBackground(String... symbol) {
        String result = "";
        DefaultHttpClient client = new DefaultHttpClient();
        String srt = "";

        String url = context.getString(R.string.urlaternativo).concat(
                symbol[0]);

        HttpGet getMethod = new HttpGet(url);
        try {
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            srt = client.execute(getMethod, responseHandler);
            int inizio = srt.indexOf("<last data=\"");
            int fine = srt.indexOf("\"/>", inizio + 12);
            result = srt.substring(inizio + 12, fine);

        } catch (Throwable t) {
            // Log.e("ERROR", "ERROR", t);
        }
        //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute()    <----
        return result;
    }
}

【问题讨论】:

  • 这是可行的,但不推荐通过Asynctask.get(),我已经在this answer 中解释了这个特殊的API。
  • 为什么不直接将 RemoteViews 传递给 AsyncTask UpdateTaskPrice 的构造函数和 setTextViewText 在 onPostExecute 中?这样,每个 AsyncTask 都知道要更新哪个 View,你甚至不需要结果
  • 使用意向服务。这已经足够同步了。
  • 你想要所有结果在哪里?

标签: android service android-asynctask


【解决方案1】:

AsyncTask 是异步的,并在单独的线程中运行。因此,在执行完 AsyncTask 后的下一条语句中是不可能得到它的结果的。

要从 AsyncTask 中获取相关结果,请在 UpdateTaskPrice 类中添加一个成员变量“mRequestId”,并在调用 UpdateTaskPrice.execute 之前设置唯一的请求 ID。

在你的UpdateTaskPrice类的“onPostExecute”方法中,你可以使用这个Request Id返回并处理结果。

public class UpdateTaskPrice extends AsyncTask<String, Void, String> {

    protected int mRequestId;

    public void setRequestId (int requestId)
    {
        this.mRequestId = requestId;
    }

    @Override
    protected void onProgressUpdate(Void... progress) {
    }

    @Override
    protected void onPostExecute(String result) {
        // do whatever with result using mRequestId
    }

    @Override
    protected String doInBackground(String... symbol) {
        String result = "";
        DefaultHttpClient client = new DefaultHttpClient();
        String srt = "";

        String url = context.getString(R.string.urlaternativo).concat(
                symbol[0]);

        HttpGet getMethod = new HttpGet(url);
        try {
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            srt = client.execute(getMethod, responseHandler);
            int inizio = srt.indexOf("<last data=\"");
            int fine = srt.indexOf("\"/>", inizio + 12);
            result = srt.substring(inizio + 12, fine);

        } catch (Throwable t) {
            // Log.e("ERROR", "ERROR", t);
        }
        //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute()    <----
        return result;
    }
}

【讨论】:

  • 非常感谢!我怀疑我必须做类似的事情。请问您是否可以详细说明答案,因为我不太确定如何将结果和 requestId 传递给getPricemethod。再次感谢!
  • AsyncTasks 旨在在后台运行。为了显示 getPrice 方法返回的结果,您需要更新 Activity 的视图。 onPostExecute 方法在 Activity 的主线程中运行。如果您在 UpdateTaskPrice 中传递您的活动的引用(与 mRequestId 相同),那么您可以在 onPostExecute 方法中访问 Activity 的视图。您还可以调用您的活动的另一个方法来负责解析结果并显示从结果中解析的价格
  • 谢谢。我明白了,但我不明白......请阿米特你能告诉我我应该如何修改代码吗?谢谢!
  • 在你的 asynctask 类中声明一个私有变量 mActivityRef。在调用 execute() 之前将 mActivityRef 设置为您当前的活动。假设您的活动中有 updatePrice 功能。在 onPostExecute 方法中,调用 mActivityRef.updatePrice(result)。您的更新结果函数负责更新文本视图,例如 ((TextView) findViewById (R.id.price)).setText (result)。
【解决方案2】:

你可以从多个asynctask中获取数据,但是你想要结果的地方是不可能的 使用 asyctask,您需要使用更多的封装来构造这个问题。

你的结构的问题是......

 private static String getPrice(String symbol) {
    String result="";
    UpdateTaskPrice up = new UpdateTaskPrice();
    up.execute(symbol, null, null);
    //HERE I WANT THE RESULT FROM onPostExecute()    <----
    return result;
}

当你启动新线程时,它会首先执行 task.execute(symbol); 之后返回的语句在您的情况下,它是 return 语句,然后它将执行 pre.. doin.. 和 post...

Hear 是您可以用来从多个 AsycTask 中检索数据的模式

//Calling to the method callAsyncTask;
callAsyncTask(new AsyncResultCallback(){
    public void onResult(String result, String symbol){
        //TODO dosomthing with the result
    }
});


public void callAsyncTask(AsyncResultCallback callback){
    new UpdateTaskPrice(callback).execurte(symbol);
}

public interface AsyncResultCallback{
    public void onResult(String result, String symbol);
}

public class UpdateTaskPrice extends AsyncTask<String, Void, String> {

    AsyncResultCallback callback;
    String symbol;

    UpdateTaskPrice(AsyncResultCallback callback){
        this.callback = callback;
    }

    @Override
    protected void onProgressUpdate(Void... progress) {
    }

    @Override
    protected void onPostExecute(String result) {
        callback.onResult(result, symbol);
    }

    @Override
    protected String doInBackground(String... symbol) {
        this.symbol = symbol;
        String result = "";
        DefaultHttpClient client = new DefaultHttpClient();
        String srt = "";

        String url = context.getString(R.string.urlaternativo).concat(symbol[0]);

        HttpGet getMethod = new HttpGet(url);
        try {
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            srt = client.execute(getMethod, responseHandler);
            int inizio = srt.indexOf("<last data=\"");
            int fine = srt.indexOf("\"/>", inizio + 12);
            result = srt.substring(inizio + 12, fine);

        } catch (Throwable t) {
            // Log.e("ERROR", "ERROR", t);
        }
            //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute()    <----
        return result;
    }
}

希望有所帮助。

【讨论】:

    【解决方案3】:

    好吧,我认为您可以在AsyncTask 的构造函数中传递唯一的请求ID。然后在postExecute() 方法中,用结果和唯一的请求id 更新UI -

    public class UpdateTaskPrice extends AsyncTask<String, Void, String> {
    
        private int mIdentifier;
        private Service mService;
    
        public UpdateTaskPrice(Service service, int identifier) {
            this.mIdentifier = identifier;
        }
    
        @Override
        protected void onProgressUpdate(Void... progress) {
        }
    
        @Override
        protected void onPostExecute(String result) {
            ((UpdateService) mService).informPrice(mIdentifier, result);
        }
    
        @Override
        protected String doInBackground(String... symbol) {
            String result = "";
            DefaultHttpClient client = new DefaultHttpClient();
            String srt = "";
    
            String url = context.getString(R.string.urlaternativo).concat(
                    symbol[0]);
    
            HttpGet getMethod = new HttpGet(url);
            try {
                ResponseHandler<String> responseHandler = new BasicResponseHandler();
                srt = client.execute(getMethod, responseHandler);
                int inizio = srt.indexOf("<last data=\"");
                int fine = srt.indexOf("\"/>", inizio + 12);
                result = srt.substring(inizio + 12, fine);
    
            } catch (Throwable t) {
                // Log.e("ERROR", "ERROR", t);
            }
            //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute()    <----
            return result;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      相关资源
      最近更新 更多