麻烦的异步任务和程序流程

时间:2014-03-06 20:13:21

标签: java android multithreading asynchronous

我目前正在设计一款应用程序,让用户可以阅读新闻文章,以及从互联网获取信息以填充列表并将其显示给用户所必需的应用程序。我已经完成了所有的解析工作,并且正确地返回了文章的正确信息。我的应用程序中有一个带有片段的主要活动,这些活动是使用视图寻呼机进行设置的。所以我有三个用户可以切换的选项卡。这看起来类似于目前市场上的Zedge应用程序。既然我有单独的片段,那么将Async任务放在我的应用程序中是一个明智的地方吗?

我打算将它放在main活动的onCreate方法中,但由于异步任务在后台同时在UI线程中运行,因为异步任务尚未完成,因此设置为空白,其中没有任何内容。似乎当我的asyc任务是postExecute方法时,UI设置已完成或几乎完成,并且应该从异步任务返回的变量(arraylist)为空。而且我猜我不能将返回的onPostExecute值分配给静态变量,因为我不知道什么时候异步任务将与UI线程相关?

我还有另一个想法,即在其类中放置更新片段UI的方法,并让onPostExecute调用它们来修改内容(即重新填充UI元素)。我知道让UI线程明确等待不是一个好主意,所以我试图避免这种情况。我的异步任务至少可以吗?希望我所说的一切听起来并不像是一堆混乱。如果有人可以帮我理解如何加载我的应用程序的信息,我当然会很感激!

private class GetArticlesFromRSS extends
        AsyncTask<Void, Void, ArrayList<Article>>
{

    ArrayList<Article> retArtList = new ArrayList<Article>();
    ProgressDialog dialog = new ProgressDialog(MainActivity.this);


    @Override
    protected void onPreExecute() {
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setMessage("Loading...");
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();
        }

    @Override
    protected ArrayList<Article> doInBackground(Void... v)
    {

        // TODO Auto-generated method stub
        artReaderObj = new ArticleRSSReader(urlArticles);

        try
        {
            artReaderObj.fetchXML();
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch(IOException ioe)
        {

            task1.cancel(true);

        }

        while (artReaderObj.parsingComplete)
            ;
        retArtList.addAll(artReaderObj.getArticles());


        return retArtList;
    }

    @Override
    protected void onPostExecute(ArrayList<Article> result)
    {
        dialog.dismiss();
        articlesReturned = result;


        if (MainActivity.articlesReturned.size() > 0){
            Toast.makeText(getApplicationContext(), "Ok", Toast.LENGTH_LONG).show();
        }
        else{
            Toast.makeText(getApplicationContext(), "Error, Check Network Connection.", Toast.LENGTH_LONG).show();
        }

    }

}

3 个答案:

答案 0 :(得分:1)

我认为在这种情况下使用服务会更好。当UI需要更新时,可以绑定服务并获取信息。

答案 1 :(得分:1)

没有必要让UI线程等待......

postExecute在UI线程上运行,因此您可以从该方法设置ui元素。您应该定义如何在Acivity / Fragments中设置它们,然后让post执行调用这些方法以及更新UI的信息。

此外,膨胀视图需要几分之一秒。您可以在充气后启动异步任务,以确保UI元素存在。或者你可以做一些更复杂的事情,比如如果你需要在通胀之前启动异步来缓存结果(并且它可能在应用程序完成之前返回)。

答案 2 :(得分:1)

有一个简单的解决方案可以克服并返回任何类/活动/片段中的数据。

您已在asynctask类中编写自定义侦听器(在您的情况下为GetArticlesFromRSS)并使用onPostExecute方法调用侦听器。

监听器的例子

    public interface OnAsyncResult {  
        public abstract void onResultSuccess(ArrayList<Article> result);  
        public abstract void onResultFail(int resultCode, String errorMessage);  
   }

在“GetArticlesFromRSS.java”中的OnAsyncResult上创建对象 让我们说

OnAsyncResult onAsyncResult = null;

setOnAsyncResult(OnAsyncResult callBack)
{
  this.onAsyncResult = callback;
}

然后在你的post执行方法中你可以使用这个监听器,如下所示

@Override
protected void onPostExecute(ArrayList<Article> result)
{
    dialog.dismiss();
    articlesReturned = result;


    if (MainActivity.articlesReturned.size() > 0){
        if(onAsyncResult!=null)
            onAsyncResult.onResultSuccess(result);

        Toast.makeText(getApplicationContext(), "Ok", Toast.LENGTH_LONG).show();
    }
    else{
        if(onAsyncResult!=null)
            onAsyncResult.onResultFail(1, "Error, Check Network Connection.");

        Toast.makeText(getApplicationContext(), "Error, Check Network Connection.", Toast.LENGTH_LONG).show();
    }

}

这将解决您的目的。