等待异步任务完成

时间:2012-11-26 14:50:11

标签: android drupal android-asynctask

我正在做我的第一个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));
    }

所以问题就在于此。有没有更好的方法,或有没有办法等待列表填写。

2 个答案:

答案 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上显示视频。当然,这只是一个粗略的草案,但我认为你可以得到这个想法。