【问题标题】:AsyncTask - missing something [closed]AsyncTask - 缺少一些东西[关闭]
【发布时间】:2018-03-21 17:29:07
【问题描述】:

我正在做一些项目,但我被卡住了……我做错了,可能是 AsyncTask,我不知道要修复什么以及如何修复……我现在有代码。

ReviewData.class

public class ReviewData implements Parcelable {

private String mAuthor, mContent;

public ReviewData(String author, String content) {
    this.mAuthor = author;
    this.mContent = content;
}

private ReviewData(Parcel in) {
    mAuthor = in.readString();
    mContent = in.readString();
}

public static final Creator<ReviewData> CREATOR = new Creator<ReviewData>() {
    @Override
    public ReviewData createFromParcel(Parcel in) {
        return new ReviewData(in);
    }

    @Override
    public ReviewData[] newArray(int size) {
        return new ReviewData[size];
    }
};

//Getter method for review author
public String getAuthor() {
    return mAuthor;
}

//Setter method for review author
public void setAuthor(String author) {
    this.mAuthor = author;
}

//Getter method for review content
public String getContent() {
    return mContent;
}

//Setter method for review content
public void setContent(String content) {
    this.mContent = content;
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(mAuthor);
    dest.writeString(mContent);
}

}

ReviewAdapter.class

public class ReviewAdapter extends RecyclerView.Adapter<ReviewAdapter.ReviewViewHolder> {

private ArrayList<ReviewData> mReviewList;
private Context mContext;

public ReviewAdapter(Context context, ArrayList<ReviewData> reviewList) {
    this.mContext = context;
    this.mReviewList = reviewList;
}

@Override
public ReviewViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    mContext = parent.getContext();
    View view = LayoutInflater.from(mContext).inflate(R.layout.review_item_list,
            parent, false);
    view.setFocusable(true);
    return new ReviewViewHolder(view);
}

@Override
public void onBindViewHolder(final ReviewViewHolder holder, int position) {
    if(mReviewList != null) {
        ReviewData reviewData = mReviewList.get(position);
        holder.reviewAuthor.setText(reviewData.getAuthor());
        holder.reviewContent.setText(reviewData.getContent());
    }
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemCount() {
    if(mReviewList == null) {
        return  0;
    } else {
        return mReviewList.size();
    }
}

public void setReviewList(ArrayList<ReviewData> reviewList) {
    if(reviewList != null) {
        mReviewList = new ArrayList<>(reviewList);
    }
    notifyDataSetChanged();
}

public class ReviewViewHolder extends RecyclerView.ViewHolder {

    TextView reviewAuthor;
    TextView reviewContent;

    public ReviewViewHolder(View itemView) {
        super(itemView);
        reviewAuthor = itemView.findViewById(R.id.review_author);
        reviewContent = itemView.findViewById(R.id.review_content);
    }
}

}

NetworkUtils.class(但只有 Review url builder 的代码,其他东西可以完美运行)。 PS。此解析是按照 API 文档所述编写的……它应该是 someurl/movie/{id}/reviews

//URL builder for reviews
public static URL buildReviewUrl(String id) {
    Uri builtUri = Uri.parse(BASE_MOVIE_URL + id + REVIEW).buildUpon()
            .appendQueryParameter(QUERY_API_KEY, API_KEY)
            .build();

    URL url = null;
    try {
        url = new URL(builtUri.toString());
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }

    return url;
}

JsonData.类(也,仅用于评论,其他作品完美...)

//JSON for Review
public static ArrayList<ReviewData> getReviewFromJson(String json) throws JSONException {
    ArrayList<ReviewData> listOfReviews = new ArrayList<>();

    try {
        JSONObject reviews = new JSONObject(json);
        JSONArray reviewsArray = reviews.getJSONArray(QUERY_RESULTS);
        for(int i = 0; i < reviewsArray.length(); i++) {
            JSONObject jsonReview = reviewsArray.getJSONObject(i);
            String author = jsonReview.optString(REVIEW_AUTHOR);
            String content = jsonReview.optString(REVIEW_CONTENT);

            ReviewData reviewData = new ReviewData(author, content);

            listOfReviews.add(reviewData);
        }
    } catch(JSONException e) {
        e.printStackTrace();
        Log.e("ReviewJson", "JSON Review Error");
    }

    return listOfReviews;
}

ReviewAsyncTask.class

public class ReviewAsyncTask extends AsyncTask<String, Void, ArrayList<ReviewData>> {

private ReviewData mReviewData;

public interface ReviewResponse {
    void finished(ArrayList<ReviewData> output);
}

private ReviewResponse reviewResponse = null;

public ReviewAsyncTask(ReviewResponse reviewResponse) {
    this.reviewResponse = reviewResponse;
}

@Override
protected ArrayList<ReviewData> doInBackground(String... strings) {
    String rawData = "";
    ArrayList<ReviewData> reviewList = new ArrayList<>();
    try {
        rawData = NetworkUtils.getResponseFromHttpRequest(NetworkUtils
                .buildReviewUrl(String.valueOf(mReviewData)));
        reviewList = JsonData.getReviewFromJson(rawData);
    } catch (IOException e) {
        e.printStackTrace();
        Log.e("ReviewAsyncTask", "Error in ReviewAsyncTask");
    } catch (JSONException e) {
        e.printStackTrace();
        Log.e("JSONAsync", "JSON problem");
    }

    return reviewList;
}

@Override
protected void onPostExecute(ArrayList<ReviewData> reviewData) {
    reviewResponse.finished(reviewData);

}

}

和 MovieDetails 活动(一切正常,除了从评论回收审查到下一条评论。

public class MovieDetails extends AppCompatActivity implements ReviewAsyncTask.ReviewResponse {

private final static String BASE_URL = "http://image.tmdb.org/t/p/";
private final static String SIZE = "w185/";

private ArrayList<ReviewData> mReviewList;

private ReviewAdapter mReviewAdapter;

@BindView(R.id.poster_detail)
ImageView mMoviePoster;
@BindView(R.id.title_detail)
TextView mMovieTitle;
@BindView(R.id.release_date)
TextView mReleaseDate;
@BindView(R.id.average_vote)
TextView mAverageVote;
@BindView(R.id.synopsis)
TextView mSynopsis;

@BindView(R.id.review_recycler)
RecyclerView mReviewRecycle;

Context mContext;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_movie_details);
    ButterKnife.bind(this);

    displayMovieDetail();

    //Review RecycleView
    mReviewList = new ArrayList<>();
    mReviewAdapter = new ReviewAdapter(this, mReviewList);

    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
    mReviewRecycle.setLayoutManager(layoutManager);
    mReviewRecycle.setHasFixedSize(true);
    mReviewRecycle.setAdapter(mReviewAdapter);
}

@Override
public void finished(ArrayList<ReviewData> output) {
    ReviewAsyncTask reviewAsyncTask = new ReviewAsyncTask(this);
    reviewAsyncTask.execute();
}

/* Method for displaying the info about movies in activity details
 * @param mMoviePoster sets the movie poster
 * @param mMovieTitle sets original title of the movie
 * @param mReleaseDate sets release date of the movie
 * @param mAverageVote sets average rating grade of the movie
 * @param mSynopsis sets plot of the movie */
private void displayMovieDetail() {
    int idMovie = (Integer) getIntent().getExtras().get(getString(R.string.movie_id));

    List<MovieData> movieList;
    movieList = getIntent().getParcelableArrayListExtra(getString(R.string.movie_lsit));

    MovieData movieData = movieList.get(idMovie);

    Picasso.with(mContext).load(BASE_URL + SIZE +
            movieData.getPoster()).into(mMoviePoster);
    mMovieTitle.setText(movieData.getTitle());
    mReleaseDate.setText(movieData.getReleaseDate());
    mAverageVote.setText(Double.toString(movieData.getRating()));
    mSynopsis.setText(movieData.getSynopsis());
}

}

附:我会分享 github 链接,但我应该给你我的个人 API 密钥。 :(

【问题讨论】:

  • 到底是什么问题?
  • @plaskoff 评论不显示...
  • 您是否尝试检查响应?您收到回复了吗?
  • 你在 AsyncTask 实现中覆盖 onPostExecute() 吗?
  • 那么我认为这就是缺少的:doInBackground() 返回一个 ArrayList,它将被传递给 onPostExecute()。覆盖它以将数据添加到适配器的数据列表中。

标签: java android android-recyclerview android-asynctask


【解决方案1】:

您需要在onCreate() 中启动AsyncTask(就像您之前所做的那样)并在finished() 中获取结果并将它们添加到适配器的数据列表中。 最后别忘了拨打notifyDatasetChanged()

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_movie_details);
    // skipping some lines of code here...
    mReviewRecycle.setAdapter(mReviewAdapter);
    ReviewAsyncTask reviewAsyncTask = new ReviewAsyncTask(this);
    reviewAsyncTask.execute();
}

@Override
public void finished(ArrayList<ReviewData> output) {
    mReviewList.addAll(output);
    mReviewAdapter.notifyDatasetChanged();
}

(请注意,为简洁起见,我跳过了 null 检查和错误处理)

【讨论】:

  • 它仍然在链接中显示 /null/ for id :(
  • @Ivan Bumbak - AsyncTask 有一个字段 mReviewData。你在哪里给它赋值?
  • 那件事困扰着我......我必须在 .buildReviewUrl 中放入一些字符串,所以如果您输入 ReviewData 值或除字符串之外的其他任何内容,我需要使用 String.valueOf() .... 和在 postExecute reviewData 中自动为 ArrayList ...
  • @Ivan Bumbak - 好吧,您必须使用有效的 Url 才能获取评论。现在,mReviewData 似乎保持为空,因此 String.valueOf(mReviewData) 为“null”。为什么不使用一些硬编码的字符串作为 Url,直到您能够完成其余的工作(获取评论并在应用程序中显示它们)?稍后您可以利用 AsyncTask > 的事实,您可以将 Url 作为条目传递给 execute() 的 String[] 参数,并从 doInBackground(String. .. 字符串)
  • 我尝试使用 ''0'',应用程序工作但没有显示任何内容,因为没有具有该 ID 的电影 .... api.themoviedb.org/3/movie/0/reviews?api_key= ... 这是正确的链接,但是而不是这个 ''0'' 应该很长 String id ...这就是我无法得到的
【解决方案2】:
  1. 在 MovieDetails onCreate 中检索当前电影 ID,就像在 displayMovieDetail 中一样。
  2. 将该 ID 发送到 ReviewAsyncTask(您需要修改 ReviewAsyncTask 的构造函数)
  3. 在 ReviewAsyncTask 中检索 id,将其保存为成员变量,然后在 doInBackground 方法中将该 id 作为参数发送到 buildReviewUrl。

【讨论】:

  • 也许您可以提供一些代码和您的建议,以更好地展示如何做到这一点?
猜你喜欢
  • 1970-01-01
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2021-08-04
  • 2013-10-20
  • 1970-01-01
相关资源
最近更新 更多