Android 如何从AsyncTaskLoader传递变量
我使用TMDB API制作了一个电影搜索应用程序,但TMDB总是在页面中给出结果,每页20个结果,所以我需要安排页面选择的界面 我使用AsyncTaskLoader发出异步API请求,但除了返回值之外,我不知道如何从后台进程发送变量 这是我的AsyncTaskLoader类:Android 如何从AsyncTaskLoader传递变量,android,asynctaskloader,Android,Asynctaskloader,我使用TMDB API制作了一个电影搜索应用程序,但TMDB总是在页面中给出结果,每页20个结果,所以我需要安排页面选择的界面 我使用AsyncTaskLoader发出异步API请求,但除了返回值之外,我不知道如何从后台进程发送变量 这是我的AsyncTaskLoader类: public class MovieAsyncTaskLoader extends AsyncTaskLoader<ArrayList<Movie>> { private ArrayList<
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;
}
}
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);
}
}
这是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"},
...
]
}
{“页面”:1,
“总结果”:14,
“总页数”:1,
“结果”:[
{“计票”:7143,
“id”:20352,
“视频”:假,
“平均投票数”:7.1,
“头衔”:“卑鄙的我”,
“受欢迎程度”:41.730844,
“海报路径”:“\/4zHJhBSY4kNZXfhTlmy2TzXD51M.jpg”,
“原始语言”:“en”,
“原始标题”:“卑鄙的我”,
“类型识别码”:[1610751],
“背景路径”:“\/yo1ef57MEPkEE4BDZKTZGH9uDcX.jpg”,
“成人”:假,
“概述”:“邪恶的格鲁人不辜负……”,
“发布日期”:“2010-07-08”},
{“计票”:5254,
“id”:93456,
“视频”:假,
“平均投票数”:7,
“头衔”:“卑鄙的我2”,
“人气”:56.02126,
“海报路径”:“\/KQRYYZQHKWKUG2KLUDYMJ9FAP.jpg”,
“原始语言”:“en”,
“原始标题”:“卑鄙的我2”,
“类型识别码”:[16,3510751],
“背景路径”:“\/rmgxcw8tGTmdhsWqdjGBS9uI1tO.jpg”,
“成人”:假,
“概述”:“Gru被反恶棍联盟招募到….”,
“发布日期”:“2013-06-25”},
...
]
}
在advanced中感谢您您可以创建一个界面,在加载完电影列表后收听,并使
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);
}
}
好的,我知道这不是你想听的,但我不会使用
AsyncTaskLoader
,因为它不适合httprequest,因为你会在代码中迷失方向。你能做的最好的事情就是花点时间看看这个由Square编写的库
这也避免了JSON转换会让你发疯。您可以使用GSON,这是一个伟大的工具,它也支持改装
我注意到的最后一件事是,您正在使用Parcel对对象进行序列化和反序列化。我建议您使用自动为您生成读写操作的Parceler
这些东西将帮助您的代码保持可读性和干净性。希望我能帮上点忙:)谢谢你的回答,但我遇到了另一个问题,我尝试了这个:
@Override public void on movies loaded(int total_results,int total_pages,int page){this.tvfind.setText(“find”+String.valueOf(total_results)+“movies”)}
它显示了结果,但出现此警告消息时,android.view.ViewRootImpl$CalledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图。和程序停止运行在我将tvFound.setText()
放入Rununuithread(new Runnable(){})
Thank's后,它现在工作正常
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 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
}
......
......
}