1

所以我正在使用 android/java 开发我的“hello world”应用程序,并选择做一个运动应用程序(这很奇怪......我不喜欢运动......但无论如何)。所以我设置了我的布局,允许用户“向下钻取”,这样他们就可以看到棒球、MLB 或印第安人的布局。假设用户从 MLB 视图中选择“印第安人”。我更新选项卡,可能是配色方案、背景等,并为“新闻”和“球员”选项卡加载数据(后者是团队布局所独有的)。不幸的是,api 调用有时可能需要相对较长的时间才能完成,尤其是当来自 ESPN 的免费 API 被限制为每秒 1 次调用时。我已经做了一些重要的缓存,但我无法保证我不会同时为“印第安人”加载“新闻”和“玩家”

所以我的解决方案是有一个数据加载线程——用户界面说“给我这个数据”,并且用户界面的工作是否不取决于那里的数据。但问题是——一旦数据从数据加载器返回(当每一块都返回时),它应该如何更新或适当地通知 UI?我目前的想法是:

界面线程:

OnSelectIndians()
{
  DataLoadThread.GetIndiansPlayers();
  DataLoadThread.GetIndiansNews();
  // UI stuff
}

OnPlayersLoaded(Array Players)
{
  if (layout == INDIANS_LAYOUT)  // Make sure we haven't changed layouts
  {
    foreach player in Players
      tab[PLAYERS].textview.text += player
  }
}

但这不是我以前必须处理的问题。这是正确的方法吗?或者我可以使用更好/更简单的设计吗?我并不特别喜欢要求 UI 线程对我可以请求的每种数据类型都有一个“返回数据”方法。我的另一个松散的想法是在 UI 代码中创建一个 lambda 函数,它被传递给数据加载器并在数据加载线程中执行,所以:

DataLoadThread.Queue(
    foreach player in GetIndiansPlayers()
        myView.tab[PLAYERS].textview.text += player;
);

但我认为这可能是更糟糕的路线,因为现在我们有 2 个线程与 UI 交互。有什么建议吗?

编辑:好的,我使用 AsyncTask 让它工作。开箱即用,它仍然存在上面列出的问题,如果我加载数据(例如 PlayerLoadTask、NewsLoadTask、StandingsLoadTask 等),我必须为每种类型创建一个新的派生类。我还希望在通话期间让大部分逻辑可见,所以如果我正在查看事件代码,我知道它在做什么。以下是工作实施 - 将不胜感激任何反馈,但我会接受下面的第一个答案。

抽象公共类 LoadDataHelper { public LoadDataHelper(DataLoader dl, Object param) { mDataLoader = dl; mParam = 参数;}

    abstract public LinkedList<String> LoadData();
    protected DataLoader mDataLoader;
    protected Object mParam;
}

abstract public class UpdateUIHelper {
    public UpdateUIHelper(MyActivity context) {
        mContext = context;
    }

    abstract public void UpdateUI(LinkedList<String> results);
    protected MyActivity mContext;
}

private class LoadDataTask extends AsyncTask<Void, Void, LinkedList<String> >   {
    private LoadDataHelper mLdh;
    private UpdateUIHelper mUih;

    LoadDataTask(LoadDataHelper ldh, UpdateUIHelper uih) {
        mLdh = ldh;
        mUih = uih;
    }

    @Override
    protected LinkedList<String> doInBackground(Void... params) {
        return mLdh.LoadData();
    }

    @Override
    protected void onPostExecute(LinkedList<String> results) {
        mUih.UpdateUI(results);
    }
}

//
// .....
// 

    LoadDataTask task = new LoadDataTask(new LoadDataHelper(mDataLoader, "football") {
                                            public LinkedList<String> LoadData() {                                                  
                                                return mDataLoader.LoadLeaguesFromSport((String)mParam);
                                            }
                                        }, 
                                        new UpdateUIHelper(this) {
                                            public void UpdateUI(LinkedList<String> results) {
                                                TextView tv = (TextView)findViewById(R.id.tv1);
                                                tv.setText("");
                                                for (String res : results) {
                                                    tv.append(res + "\n");  
                                                }
                                            }
                                        });
    task.execute();
4

5 回答 5

3

看一眼:

1) AsyncTask http://developer.android.com/reference/android/os/AsyncTask.html

AsyncTask.onPostExecute 将在 UI 线程中执行。我认为这是进行后台处理的最常用技术。

2)runOnUIThread:如果您正在管理自己的工作线程,您可以在工作线程中使用它来确保代码在 UI 线程上运行。

于 2012-07-11T06:10:29.547 回答
3

让UI 工作在 UI 线程中总是更好,而 Non-UI 工作在 Non-UI 线程中,但是这从 HoneyComb 在 Android 中的到来就成为了一个定律

2种方法在Android中做到这一点。

1.使用带有Handler的Java线程。。 创建一个线程来做进程繁重的后台任务,然后使用Handler显示数据...

2.使用专为Android设计的AsyncTask<>来同步UI工作和Non-UI工作。AsyncTask 也称为无痛线程。

于 2012-07-11T06:29:03.987 回答
2

这就是AsyncTask设计要做的,这是我从中学到的教程。

这是你要做的

  • 创建一个扩展类AsyncTask
  • 实现doInBackgroundonPostUpdate方法
  • onPostUpdate更新ui的方法中,您可以使用它runOnUiThread来避免在ui更新期间出现任何问题

使用异步任务的好处是您甚至可以更新进度并向用户显示可视指示器,如果需要,您可以轻松取消任务以停止加载

AsyncTask本质上是一个简化线程使用的助手

于 2012-07-11T06:27:30.033 回答
1

最好的选择是使用 AsyncTask。我创建了一个类似的应用程序,它对服务器进行了 25 次以上的调用以下载图像。使用 AsyncTask 将大大缩短时间,并且仍然提供出色的用户体验。这是关于如何使用/设置 AsyncTask 的精彩教程:

http://www.peachpit.com/articles/article.aspx?p=1823692&seqNum=3

于 2012-07-11T06:18:33.443 回答
1

异步任务是您的解决方案 这里是一个教程

于 2012-07-11T06:20:05.780 回答