所以我正在用 android/java 开发我的“hello world”应用程序,并选择做一个运动应用程序(这很奇怪......我不喜欢运动......但无论如何)。所以我设置了我的布局,允许用户“向下钻取”,这样他们就可以看到棒球、MLB 或印第安人的布局。假设用户从 MLB View 中选择“印第安人”。我更新选项卡,可能是配色方案、背景等,并加载“新闻”和“球员”选项卡的数据(后者是团队布局所独有的)。不幸的是,api 调用有时可能需要相对较长的时间才能完成,尤其是当来自 ESPN 的免费 API 的上限为每秒 1 次调用时。我已经做了一些重要的缓存,但我无法保证我不会同时加载“印第安人”的“新闻”和“玩家”,所以其中一个请求必须等待整整一秒回来。
所以我的解决方案是有一个数据加载线程——用户界面说“给我这个数据”,并且用户界面的工作是否取决于那里的数据。但问题是——一旦数据从数据加载器返回(当每一 block 都返回时),它应该如何适本地更新或通知 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 等),我将不得不为每种类型创建一个新的派生类。我还希望在调用期间让大部分逻辑可见,所以如果我查看事件代码,我就知道它在做什么。以下是有效的实现 - 希望收到任何反馈,但我会接受下面的第一个答案。
抽象公共(public)类 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();
最佳答案
看看:
1) 异步任务
http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask.onPostExecute 将在 UI 线程中执行。 我认为这是进行后台处理的最常用技术。
2) runOnUIThread:
如果您正在管理自己的工作线程,您可以在工作线程中使用它来确保代码在 UI 线程上运行。
关于java - 在android中,如何将数据加载到它自己的线程中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11426387/