我使用TMDB API制作电影搜索应用程序,但TMDB总是在每页有20个结果的页面中给出结果,所以我需要安排用于页面选择的界面。
我正在使用AsyncTaskLoader来发出异步API请求,但我不知道如何从后台进程发送变量值而不是返回值。
这是我的 AsyncTaskLoader 类:
public class MovieAsyncTaskLoader extends AsyncTaskLoader<ArrayList<Movie>> {
private ArrayList<Movie> movies;
private boolean hasResult = false;
private String keyword;
public MovieAsyncTaskLoader(final Context context, String keyword) {
super(context);
onContentChanged();
this.keyword = keyword;
}
@Override
protected void onStartLoading() {
if (takeContentChanged())
forceLoad();
else if (hasResult)
deliverResult(movies);
}
@Override
public void deliverResult(final ArrayList<Movie> data) {
movies = data;
hasResult = true;
super.deliverResult(data);
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
if (hasResult) {
onReleaseResources(movies);
movies = null;
hasResult = false;
}
}
private void onReleaseResources(ArrayList<Movie> movies) {
}
private static final String API_KEY = "323ee6e4b1621c63xxxxxxxxxxxxxxxx";
@Override
public ArrayList<Movie> loadInBackground() {
SyncHttpClient client = new SyncHttpClient();
final ArrayList<Movie> movies = new ArrayList<>();
String url = "https://api.themoviedb.org/3/search/movie?api_key=" +
API_KEY + "&language=en-US&query=" + keyword ;
client.get( url, new AsyncHttpResponseHandler() {
@Override
public void onStart() {
super.onStart();
setUseSynchronousMode(true);
}
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
String result = new String(responseBody);
JSONObject responseObject = new JSONObject(result);
// how to passing these variabels out to MainActivity ??
Integer total_results = responseObject.getInt("total_results");
Integer total_pages = responseObject.getInt("total_pages");
Integer page = responseObject.getInt("page");
JSONArray list = responseObject.getJSONArray("results");
for (int i = 0 ; i < list.length() ; i++){
JSONObject movieitem = list.getJSONObject(i);
Movie movie = new Movie(movieitem);
movies.add(movie);
}
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
}
});
return movies;
}
}
这是我的 MainActivity 类:
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<ArrayList<Movie>> {
MovieListAdapter adapter;
ListView movielist;
EditText etKeyword;
Button btSearch;
TextView tvFound;
public Integer total_results;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = new MovieListAdapter(this);
adapter.notifyDataSetChanged();
movielist = (ListView) findViewById(R.id.lvMovie);
movielist.setAdapter( adapter );
etKeyword = (EditText) findViewById(R.id.etKeyword);
String keyword = etKeyword.getText().toString();
Bundle bundle = new Bundle();
bundle.putString("keyword", keyword);
getLoaderManager().restartLoader(0, bundle, this);
btSearch = (Button) findViewById( R.id.btSearch );
btSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String keyword = etKeyword.getText().toString();
if (TextUtils.isEmpty(keyword))return;
Bundle bundle = new Bundle();
bundle.putString("keyword", keyword);
getLoaderManager().restartLoader(0, bundle, MainActivity.this);
}
});
tvFound = (TextView) findViewById(R.id.tvFound);
}
@Override
public Loader<ArrayList<Movie>> onCreateLoader(int i, Bundle bundle) {
String keyword = "";
if( bundle != null) {
keyword = bundle.getString("keyword");
}
return new MovieAsyncTaskLoader(this, keyword );
}
@Override
public void onLoadFinished(Loader<ArrayList<Movie>> loader, ArrayList<Movie> movies) {
adapter.setDatamovie( movies );
}
@Override
public void onLoaderReset(Loader<ArrayList<Movie>> loader) {
adapter.setDatamovie(null);
}
}
movielist
ListView可以很好地显示结果,但我想将total_results
放在 tvFound
TextView < / p>
这是我的电影 POJO课程:
public class Movie implements Parcelable {
private Integer voteCount;
private Integer id;
private Boolean video;
private Double voteAverage;
private String title;
private Double popularity;
private String posterPath;
private String originalLanguage;
private String originalTitle;
private List<Integer> genreIds = null;
private String backdropPath;
private Boolean adult;
private String overview;
private String releaseDate;
public Movie(JSONObject movieobject){
try {
Integer votecount = movieobject.getInt("vote_count");
Integer id = movieobject.getInt("id");
Boolean video = movieobject.getBoolean("video");
Double voteaverage = movieobject.getDouble("vote_average");
String title = movieobject.getString("title");
Double popularity = movieobject.getDouble("popularity");
String posterpath = movieobject.getString("poster_path");
String originallanguage = movieobject.getString("original_language");
String originaltitle = movieobject.getString("original_title");
List<Integer> genreid = (List<Integer>) movieobject.optJSONArray("genre_id");
String backdroppath = movieobject.getString("backdrop_path");
Boolean adult = movieobject.getBoolean("adult");
String overview = movieobject.getString("overview");
String releasedate = movieobject.getString("release_date");
this.voteCount = votecount;
this.id = id;
this.video = video;
this.voteAverage = voteaverage;
this.title = title;
this.popularity = popularity;
this.posterPath = posterpath;
this.originalLanguage = originallanguage;
this.originalTitle = originaltitle;
this.genreIds = genreid;
this.backdropPath = backdroppath;
this.adult = adult;
this.overview = overview;
this.releaseDate = releasedate;
} catch (JSONException e) {
e.printStackTrace();
}
}
public Integer getVoteCount() {
return voteCount;
}
public void setVoteCount(Integer voteCount) {
this.voteCount = voteCount;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Boolean getVideo() {
return video;
}
public void setVideo(Boolean video) {
this.video = video;
}
public Double getVoteAverage() {
return voteAverage;
}
public void setVoteAverage(Double voteAverage) {
this.voteAverage = voteAverage;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Double getPopularity() {
return popularity;
}
public void setPopularity(Double popularity) {
this.popularity = popularity;
}
public String getPosterPath() {
return posterPath;
}
public void setPosterPath(String posterPath) {
this.posterPath = posterPath;
}
public String getOriginalLanguage() {
return originalLanguage;
}
public void setOriginalLanguage(String originalLanguage) {
this.originalLanguage = originalLanguage;
}
public String getOriginalTitle() {
return originalTitle;
}
public void setOriginalTitle(String originalTitle) {
this.originalTitle = originalTitle;
}
public List<Integer> getGenreIds() {
return genreIds;
}
public void setGenreIds(List<Integer> genreIds) {
this.genreIds = genreIds;
}
public String getBackdropPath() {
return backdropPath;
}
public void setBackdropPath(String backdropPath) {
this.backdropPath = backdropPath;
}
public Boolean getAdult() {
return adult;
}
public void setAdult(Boolean adult) {
this.adult = adult;
}
public String getOverview() {
return overview;
}
public void setOverview(String overview) {
this.overview = overview;
}
public String getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(String releaseDate) {
this.releaseDate = releaseDate;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(this.voteCount);
dest.writeValue(this.id);
dest.writeValue(this.video);
dest.writeValue(this.voteAverage);
dest.writeString(this.title);
dest.writeValue(this.popularity);
dest.writeString(this.posterPath);
dest.writeString(this.originalLanguage);
dest.writeString(this.originalTitle);
dest.writeList(this.genreIds);
dest.writeString(this.backdropPath);
dest.writeValue(this.adult);
dest.writeString(this.overview);
dest.writeString(this.releaseDate);
}
protected Movie(Parcel in) {
this.voteCount = (Integer) in.readValue(Integer.class.getClassLoader());
this.id = (Integer) in.readValue(Integer.class.getClassLoader());
this.video = (Boolean) in.readValue(Boolean.class.getClassLoader());
this.voteAverage = (Double) in.readValue(Double.class.getClassLoader());
this.title = in.readString();
this.popularity = (Double) in.readValue(Double.class.getClassLoader());
this.posterPath = in.readString();
this.originalLanguage = in.readString();
this.originalTitle = in.readString();
this.genreIds = new ArrayList<Integer>();
in.readList(this.genreIds, Integer.class.getClassLoader());
this.backdropPath = in.readString();
this.adult = (Boolean) in.readValue(Boolean.class.getClassLoader());
this.overview = in.readString();
this.releaseDate = in.readString();
}
public static final Parcelable.Creator<Movie> CREATOR = new Parcelable.Creator<Movie>() {
@Override
public Movie createFromParcel(Parcel source) {
return new Movie(source);
}
@Override
public Movie[] newArray(int size) {
return new Movie[size];
}
};
}
这是TMDB API请求的结果示例:
{"page":1,
"total_results":14,
"total_pages":1,
"results":[
{"vote_count":7143,
"id":20352,
"video":false,
"vote_average":7.1,
"title":"Despicable Me",
"popularity":41.730844,
"poster_path":"\/4zHJhBSY4kNZXfhTlmy2TzXD51M.jpg",
"original_language":"en",
"original_title":"Despicable Me",
"genre_ids":[16,10751],
"backdrop_path":"\/yo1ef57MEPkEE4BDZKTZGH9uDcX.jpg",
"adult":false,
"overview":"Villainous Gru lives up to ... <deleted> .",
"release_date":"2010-07-08"},
{"vote_count":5254,
"id":93456,
"video":false,
"vote_average":7,
"title":"Despicable Me 2",
"popularity":56.02126,
"poster_path":"\/kQrYyZQHkwkUg2KlUDyvymj9FAp.jpg",
"original_language":"en",
"original_title":"Despicable Me 2",
"genre_ids":[16,35,10751],
"backdrop_path":"\/rmgxcw8tGTmdhsWqdjGBS9uI1tO.jpg",
"adult":false,
"overview":"Gru is recruited by the Anti-Villain League to ... <deleted>.",
"release_date":"2013-06-25"},
...
]
}
先谢谢你了
答案 0 :(得分:0)
您可以在完成加载电影列表时创建一个用于收听的界面,并使MainActivity
实现此界面。
public class MovieAsyncTaskLoader extends AsyncTaskLoader<ArrayList<Movie>> {
private ArrayList<Movie> movies;
private boolean hasResult = false;
private String keyword;
private MoviesLoadingListener listener; //MainActivity
public MovieAsyncTaskLoader(final Context context, String keyword, MoviesLoadingListener listener) {
super(context);
onContentChanged();
this.keyword = keyword;
this.listener = listener; //set MainActivity as the listener
}
.....
.....
@Override
public ArrayList<Movie> loadInBackground() {
SyncHttpClient client = new SyncHttpClient();
final ArrayList<Movie> movies = new ArrayList<>();
String url = "https://api.themoviedb.org/3/search/movie?api_key=" +
API_KEY + "&language=en-US&query=" + keyword ;
client.get( url, new AsyncHttpResponseHandler() {
@Override
public void onStart() {
super.onStart();
setUseSynchronousMode(true);
}
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
String result = new String(responseBody);
JSONObject responseObject = new JSONObject(result);
// how to passing these variabels out to MainActivity ??
Integer total_results = responseObject.getInt("total_results");
Integer total_pages = responseObject.getInt("total_pages");
Integer page = responseObject.getInt("page");
//here you pass the three integers to MainActivity
listener.onMoviesLoaded(total_results, total_pages, page);
JSONArray list = responseObject.getJSONArray("results");
for (int i = 0 ; i < list.length() ; i++){
JSONObject movieitem = list.getJSONObject(i);
Movie movie = new Movie(movieitem);
movies.add(movie);
}
}catch (Exception e){
e.printStackTrace();
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
}
});
return movies;
}
//This is the interface that MainActivity will implement
public interface MoviesLoadingListener {
void onMoviesLoaded(int total_results, int total_pages, int page);
}
}
MainActivity
代码:
//MainActivity implements the interface we created
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<ArrayList<Movie>>,
MovieAsyncTaskLoader.MoviesLoadingListener {
......
......
@Override
public Loader<ArrayList<Movie>> onCreateLoader(int i, Bundle bundle) {
String keyword = "";
if( bundle != null) {
keyword = bundle.getString("keyword");
}
//here you pass the activity as the listener in the third parameter
return new MovieAsyncTaskLoader(this, keyword, this );
}
......
......
@Override
public void onMoviesLoaded(int total_results, int total_pages, int page) {
//do whatever you need with the three integers here
}
......
......
}
答案 1 :(得分:0)
好的,我知道这不是你想听到的,但我不会使用AsyncTaskLoader
,因为它不适合HttpRequests,因为你会迷失在代码中。你可以做的最好的事情是投入一些时间来查看Square http://square.github.io/retrofit/编写的这个库。
这也避免了你的JSON转换会让你疯狂。您可以使用GSON,它是一个很棒的工具,它也受到Retrofit的支持。
最后我注意到你正在使用Parcel来序列化和反序列化你的对象。我建议你使用Parceler自动为你生成读写。
这些东西将帮助您的代码保持可读性和清洁性。希望我有所帮助:)