Java 在android中管理多个异步任务

Java 在android中管理多个异步任务,java,android,asynchronous,Java,Android,Asynchronous,大家好,我刚刚开始在线培训应用程序的第二部分,并尝试调整我的异步任务以从电影数据库获取电影评论。有一个完全不同的异步任务似乎应该有一个更好的方法。下面是当前仅获取电影数据的异步任务实现 问题是我如何添加另一个异步任务,以便从这个url/movie/{id}/videos检索电影评论 public FetchMovieData(Context context, GridView grid, boolean sortType, ITaskCompleteListener listener) {

大家好,我刚刚开始在线培训应用程序的第二部分,并尝试调整我的异步任务以从电影数据库获取电影评论。有一个完全不同的异步任务似乎应该有一个更好的方法。下面是当前仅获取电影数据的异步任务实现

问题是我如何添加另一个异步任务,以便从这个url/movie/{id}/videos检索电影评论

public FetchMovieData(Context context, GridView grid, boolean sortType, ITaskCompleteListener listener) {
    mContext = context;
    this.mMoviesGrid = grid;
    this.mSortByMostPopular = sortType;
    this.mTaskCompleteListener = listener;
}

@Override
protected Void doInBackground(String... params) {

    // These two need to be declared outside the try/catch
    // so that they can be closed in the finally block.
    HttpURLConnection urlConnection = null;
    BufferedReader reader = null;

    try {
        URL url;
        if(mSortByMostPopular)
            url = new URL(mContext.getString(R.string.picasso_url_popular_movies));
        else
            url = new URL(mContext.getString(R.string.picasso_url_highest_rated));

        // Create the request to OpenWeatherMap, and open the connection
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setRequestMethod("GET");
        urlConnection.connect();

        // Read the input stream into a String
        InputStream inputStream = urlConnection.getInputStream();
        StringBuffer buffer = new StringBuffer();
        if (inputStream == null) {
            // Nothing to do.
            mMovieJsonStr = null;
        }
        reader = new BufferedReader(new InputStreamReader(inputStream));

        String line;
        while ((line = reader.readLine()) != null) {
            // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
            // But it does make debugging a *lot* easier if you print out the completed
            // buffer for debugging.
            buffer.append(line + "\n");
        }

        if (buffer.length() == 0) {
            // Stream was empty.  No point in parsing.
            mMovieJsonStr = null;
        }
        mMovieJsonStr = buffer.toString();
    } catch (IOException e) {
        Log.e("PlaceholderFragment", "Error ", e);
        // If the code didn't successfully get the weather data, there's no point in attempting
        // to parse it.
        mMovieJsonStr = null;
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect();
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (final IOException e) {
                Log.e("PlaceholderFragment", "Error closing stream", e);
            }
        }
    }

    return null;
}

@Override
protected void onPostExecute(Void aVoid) {
    super.onPostExecute(aVoid);
    if(mMovieJsonStr != null)
        Constants.mMovies = MovieDataParser.getMovieData(mMovieJsonStr);

    mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
}
因此,有人建议使用改造,而不是有多个异步任务。这似乎是个好主意,但我很难理解它应该如何工作。目前,我有一个WebService类和一个接口,我正试图用它来检索这两部电影,并将添加评论,然后是预告片。问题是,如果我在logcat中将基本url设置为“I get url必须以“/”开头”

当前代码:

public class WebService {
  public List<Movie> getMovies() {

    RestAdapter retrofit = new RestAdapter.Builder()
            .setEndpoint("http://api.themoviedb.org")
            .build();

    MovieDBService service = retrofit.create(MovieDBService.class);

    return service.listMovies("movies");
   }
 }

public interface MovieDBService {
                     @GET("/3/discover/{switchterm}sort_by=popularity.desc&api_key=d273a1a1fb9390dab9  7ac0032b12366a")

  List listMovies(@Path("switchterm") String switchterm);
}

//In code getting movies
WebService service = new WebService();
List movies = service.getMovies();
公共类Web服务{
公共列表getMovies(){
RestAdapter翻新=新建RestAdapter.Builder()
.setEndpoint(“http://api.themoviedb.org")
.build();
MovieDBService=reformation.create(MovieDBService.class);
返回服务。列表电影(“电影”);
}
}
公共界面电影服务{
@GET(“/3/discover/{switchterm}sort_by=popularity.desc&api_key=d273a1fb9390dab9 7ac0032b12366a”)
列出listMovies(@Path(“switchterm”)字符串switchterm);
}
//在代码获取电影中
WebService=newwebservice();
List movies=service.getMovies();

我认为您有很多这样做的可能性。您可以遵循以下方法:在第一个任务完成后,向另一个AsyncTask添加第二个调用,并向其传递带有视频ID的字符串列表:

public class FetchMovieData extends AsyncTask<Void, Void, Void> {

    protected Boolean doInBackground() {
       try {
           String movieJSONString = getJSONMovies();
           String[] ids = parseIdsFromJSON(movieJSONString);
           if(ids.lenth != 0) {
               FetchMovieReviews moviesReviewsAsyncTask = new FetchMovieReviews();
               moviesReviewsAsyncTask.execute(ids);
           } else {
               return false;
           }

           return true;
        } catch (Exception e) {
           return false;
        }
    }

    protected String getJSONMovies() {
       //with the code you post, return the json string
    }

    protected String[] parseIdsFromJSON(String JSON) {
        //parse the json and get the ids and return
        //return {"1","2","3"}
    }
}

public class FetchMovieReviews extends AsyncTask<String[], Void, Void> {

    protected Void doInBackground(String[]... params) {
       for(String id : params[0]) {
           //call the web service and pass the id
       }

       return null;
    }
}
公共类FetchMovieData扩展异步任务{
受保护的布尔值doInBackground(){
试一试{
字符串movieJSONString=getJSONMovies();
String[]ids=parseIdsFromJSON(movieJSONString);
如果(ids.lenth!=0){
FetchMovierViews MoviesReviewAsyncTask=新建FetchMovieReviews();
MoviesReviewAsyncTask.execute(ID);
}否则{
返回false;
}
返回true;
}捕获(例外e){
返回false;
}
}
受保护的字符串getJSONMovies(){
//使用您发布的代码,返回json字符串
}
受保护的字符串[]parseIdsFromJSON(字符串JSON){
//解析json并获取ID并返回
//返回{“1”、“2”、“3”}
}
}
公共类FetchMovieReviews扩展了异步任务{
受保护的Void doInBackground(字符串[]…参数){
for(字符串id:params[0]){
//调用web服务并传递id
}
返回null;
}
}

您可以将用于管理web服务调用的所有功能放在MoviesRESTCalls类中,以及用于管理MoviesJSONParser类或类似的类中的json,代码将更加清晰。

因此,我最终使用的是web服务的翻新库。谢谢大家的帮助,让我知道你的想法

public Context mContext;
private MovieJSON mMovieData;
private ReviewJSON mMovieReviews;
private VideoJSON mMovieVideos;
public boolean mSortByMostPopular;
ITaskCompleteListener mTaskCompleteListener;

public FetchMovieData(Context context, boolean sortType, ITaskCompleteListener listener) {
    mContext = context;
    this.mSortByMostPopular = sortType;
    this.mTaskCompleteListener = listener;
}

public void getMovies() {
    new FetchMovies().execute();
}

public void getReviews() {
    new FetchReviews().execute();
}

public void getVideos() {
    new FetchTrailers().execute();
}

private class FetchMovies extends AsyncTask<String, Void, Void > {

    @Override
    protected Void doInBackground(String... params) {
        WebService service = new WebService();
        //TODO Re-Implement sorting
        mMovieData = service.getMovies();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if(mMovieData != null)
            Constants.mMovies = MovieDataParser.getMovieData(mMovieData);

        mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
    }
}

private class FetchReviews extends AsyncTask<String, Void, Void > {

    @Override
    protected Void doInBackground(String... params) {
        WebService service = new WebService();
        mMovieReviews = service.getReviews();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if(mMovieReviews != null)
            Constants.mReviews = MovieDataParser.getReviewData(mMovieReviews);

        mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
    }
}

private class FetchTrailers extends AsyncTask<String, Void, Void > {

    @Override
    protected Void doInBackground(String... params) {
        WebService service = new WebService();
        mMovieVideos = service.getVideos();
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        if(mMovieVideos != null)
            Constants.mTrailers = MovieDataParser.getVideoData(mMovieVideos);

        mTaskCompleteListener.onTaskCompleted(); //Task completed alert UI that we have our data
    }
}

}

问题是什么?在列表中添加url,并为每个url执行异步任务。确保你的asynctask序列如果你的列表很大我猜在你的电影活动中,你会显示一个电影列表。当用户单击电影时,您必须在MovieReviewActivity中显示电影评论。因此,在ListView的OnItemClickListener中,您可以启动MovieReviewAsyncTask以获取电影评论。是的,我正在为udacity电影应用程序做第二部分。Android纳米开发者学位:)。好的,我会试试这个谢谢!嗯,好的,我明白了,但是你如何保证第一个doInBackground()将在电影评论doInBackground()之前完成呢。也可以将其放入一个类而不是两个FetchMovieData类中吗?抱歉,第二个异步任务是另一个类“FetchMovieReviews”(编辑错误)。您可以使用布尔值进行管理,检查ids长度是否为零(第一个web服务调用未返回任何内容或json解析中的其他错误),然后您可以处理对其他web服务的调用以获取评论。另外,如果Http连接出现另一个错误,则抛出异常,不处理第二个doInBackground。答案已编辑!
RestAdapter mRetrofit;

MovieDBService mService;

public WebService() {
    mRetrofit = new RestAdapter.Builder()
            .setEndpoint("http://api.themoviedb.org")
            .build();
    mService = mRetrofit.create(MovieDBService.class);
}

public MovieJSON getMovies() {
    return mService.listMovies("");
}

public ReviewJSON getReviews() {
    return mService.listReviews("76341");
}

public VideoJSON getVideos() {
    return mService.listVideos("76341");
}