我正在做我的第一个Android应用程序。在其中一个页面上,我需要使用REST服务连接到Drupal站点,检索一些数据(视频URL列表,其标题,描述等)并将其显示在列表中。当我点击列表时,我会转到视频的详细信息。
以下是我想要继续的方式。 1°获取drupal站点的所有数据。 2°单击列表中的项目时,将该视频的详细信息传递给下一个活动。
问题在于: 在android 3+中连接到互联网时,你无法在主线程上进行,所以我不得不使用AsyncTask来获取数据。这有效,但后来我想将视频保存在ArrayList中,然后使用getVideos()或getVideo(索引)函数访问该列表。第一个填充列表,第二个是在转到详细信息活动之前检索数据。问题是当我尝试访问视频列表时,列表尚未填充。
从技术上讲,我并不真的需要/想要使用asynctask,但是在主线程上连接到互联网会引发一个错误,说这不是正确的做事方式。
以下是关于我如何获取视频的简化版本:
public class VideoDaoImpl {
private List<Video> videos ;
public VideoDaoImpl (){
videos = new ArrayList<Video>();
new VideoTask(...).execute(); //fetch the videos in json format and
//call function onRemoteVideoCallComplete using a handler
//in the onPostExecute() function of the asyncTask
}
public List<Video> getVideos() {
return videos;
}
public Video getVideo(int index){
return videos.get(index);
}
public onRemoteVideoCallComplete(JSONObject json) {
//transform Json into videos and add them to the videos arraylist
}
}
这就是我想在我的活动中填写视频列表的方式:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videos_list);
//get all videos (not yet filled since faster than second thread)
List<Video> videos = videoDao.getVideos();
//get a list of all the titles to display as the list
List<String> formattedVideos = VideoHelper.formatVideosList(videos);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, formattedVideos);
ListView listView = (ListView) findViewById(R.id.videos_list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new VideosListItemClickListener(this));
}
所以问题就在于此。有没有更好的方法,或有没有办法等待列表填写。
答案 0 :(得分:2)
我会保持AsyncTask不变,但是我会考虑使用onPostExecute()。在onPostExecute()中,我会将您的Json转换为视频对象列表,然后从中创建格式化视频列表。然后你可以调用一个方法将格式化视频列表传递回你的活动,然后设置列表。
例如在你的异步中:
protected void onPostExecute(Json result) {
//Create list of videos from json
//Create formatted list
//call method in activity to set list e.g activity.setList(formatted List)
}
答案 1 :(得分:0)
使用您的方法可以使预期的行为成为您所面临的行为,即视频列表尚未填充。您正在使用异步方法处理问题,但同步思考,并且您知道它,基于您的评论“由于比第二个线程更快而尚未填充”
videoDao.getVideos();
应该在你的onPostExecute方法或之后调用。我会做那样的事情,认为它是一个草案,而不是一个完整的解决方案。
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videos_list);
new VideoTask(...).execute(); // you should a use a something on your onPreExecute() inside this task showing a ProgressDialog so the user knows that something is "loading videos, please wait"
List<Video> videos = videoDao.getVideos();
if (!videos.isEmtpy()) {
//get a list of all the titles to display as the list
List<String> formattedVideos = VideoHelper.formatVideosList(videos);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, formattedVideos);
ListView listView = (ListView) findViewById(R.id.videos_list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new VideosListItemClickListener(this));
}
}
基本上它显示的区别在于您可以从VideoDAO中提取AsyncTask。使用ProgressDialog执行它以通知正在进行的操作,然后检查视频列表是否已填满。如果是,请在您的videos_list上显示视频。当然,这只是一个粗略的草案,但我认为你可以得到这个想法。