Java 如何在AsyncTask中实现自定义ArrayList?
我正在构建一个Android应用程序,它采用API(电影数据库),并提取JSON数组。提取后,将适当的JSONObject发送到模型。这个模型是一个由setter和getter组成的类,用于提取对象并将其分配给我可以使用的变量。所有这些都是在AsyncTask上完成的。然而,我很难理解doInBackground方法,因为它期望我返回一些东西。我已经完成了getMovieJson方法的所有工作,我知道我必须从doInBackground返回一些东西,因为更新onPostExecute方法上的自定义适配器需要它。此自定义适配器是一个ArrayAdapter,用于创建要在my gridView中填充的适当视图 这是我的模型Java 如何在AsyncTask中实现自定义ArrayList?,java,android,gridview,android-asynctask,android-arrayadapter,Java,Android,Gridview,Android Asynctask,Android Arrayadapter,我正在构建一个Android应用程序,它采用API(电影数据库),并提取JSON数组。提取后,将适当的JSONObject发送到模型。这个模型是一个由setter和getter组成的类,用于提取对象并将其分配给我可以使用的变量。所有这些都是在AsyncTask上完成的。然而,我很难理解doInBackground方法,因为它期望我返回一些东西。我已经完成了getMovieJson方法的所有工作,我知道我必须从doInBackground返回一些东西,因为更新onPostExecute方法上的自定
package com.xxcanizeusxx.erick.moviesnow;
/**
* This class acts as the model base for our
* array of JSON Objects that need to be populated.\
* This class uses getters and setters to achieve its task.
*/
public class Movie {
private String title;
private String vote_average;
private String overview;
private String release_date;
private String poster_path;
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
public String getOverview(){
return overview;
}
public void setOverview(String overview){
this.overview = overview;
}
public String getRelease_date(){
return release_date;
}
public void setRelease_date(String release_date){
this.release_date = release_date;
}
public String getVote_average(){
return vote_average;
}
public void setVote_average(String vote_average){
this.vote_average = vote_average;
}
public String getPoster_path(){
return poster_path;
}
public void setPoster_path(String poster_path){
this.poster_path = poster_path;
}
}
这是我的片段
package com.xxcanizeusxx.erick.moviesnow;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
/**
* Created by Erick on 1/4/2017.
*/
public class MovieFragment extends Fragment {
//Initialize our array adapter and components.
private ArrayList<Movie> mMovieData;
private MovieAdapter mMovieAdapter;
//Empty constructor
public MovieFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.movie_fragment, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.popular_movies) {
updateMovie();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateMovie() {
FetchMovieTask fetchMovie = new FetchMovieTask();
fetchMovie.execute();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Initialize our array adapter
mMovieData = new ArrayList<>();
mMovieAdapter = new MovieAdapter(getActivity(), R.layout.grid_movie_item, mMovieData);
View rootView = inflater.inflate(R.layout.gird_layout, container, false);
//Get a reference to the gridView and attach the adapter to it
GridView mGridView = (GridView) rootView.findViewById(R.id.gridView);
mGridView.setAdapter(mMovieAdapter);
return rootView;
}
@Override
public void onStart() {
super.onStart();
updateMovie();
}
public class FetchMovieTask extends AsyncTask<String[], Void, String[]> {
private final String LOG = FetchMovieTask.class.getSimpleName();
private String[] getMovieJson(String movieJsonStr) throws JSONException {
final String OWM_RESULTS = "results";
String title;
String posterPath;
JSONObject movieJson = new JSONObject(movieJsonStr);
JSONArray movieJsonArray = movieJson.getJSONArray(OWM_RESULTS);
Movie movieItem = new Movie();
//Newly created array that will house the data in order to check for views on the onPostExecute method
String[] results = new String[movieJsonStr.length()];
for (int i = 0; i < movieJsonArray.length(); i++) {
JSONObject movieObject = movieJsonArray.getJSONObject(i);
title = movieObject.getString("title");
posterPath = movieObject.getString("poster_path");
movieItem.setTitle(title);
movieItem.setPoster_path(posterPath);
results[i] = movieObject.getString(posterPath) +" " + movieObject.getString(posterPath);
}
mMovieData.add(movieItem);
return results;
}
@Override
protected String[] doInBackground(String[]... params) {
//Establish a connection
HttpURLConnection urlConnection = null;
BufferedReader bufferedReader = null;
//Will contain the raw JSON as a string
String movieJsonStr = null;
//String as placeholders
String descriptionHolder = "popularity.desc";
try {
//String to hold the Base url
final String TMDB_BASE_URL = "http://api.themoviedb.org/3/discover/movie?";
final String APPID = "api_key";
final String DESC = "sort_by";
//Build the url
Uri buildMovieUri = Uri.parse(TMDB_BASE_URL).buildUpon()
.appendQueryParameter(DESC, descriptionHolder)
.appendQueryParameter(APPID, BuildConfig.TMDP_API_KEY)
.build();
URL url = new URL(buildMovieUri.toString());
//Create the request to TMDB and open 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
return null;
}
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
//Make debugging easier by adding a new line to the bufffer stream
buffer.append(line + "\n");
int result = 1;
}
if (buffer.length() == 0) {
//stream was empty. No point in parsing.
return null;
}
movieJsonStr = buffer.toString();
} catch (IOException e) {
Log.e(LOG, "Error ", e);
//If code didnt get the movie data, no point in parsing
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (final IOException e) {
Log.e(LOG, "Error closing stream ", e);
}
}
}
try {
return getMovieJson(movieJsonStr);
} catch (JSONException e) {
Log.e(LOG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String[] result){
if (result != null){
mMovieAdapter.clear();
for (String results : result ){
mMovieAdapter.setMovieData(results);
}
}
}
}
}
我的GirdLayoutXML
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/gridView"
android:numColumns="2"
android:gravity="center"
android:drawSelectorOnTop="true"
android:verticalSpacing="5dp"
android:horizontalSpacing="5dp">
</GridView>
</FrameLayout>
My movieItem xml(用于填充gridLayout)
首先更改异步任务的参数
public class FetchMovieTask extends AsyncTask<Void, String[], String[]> {}
了解参数和返回类型的流程
更新:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.gird_layout, container, false);
//Initialize our array adapter
mMovieData = new ArrayList<>();
updateView(mMovieData);
return rootView;
}
void updateView(ArrayList<>() movieData){
mMovieAdapter = new MovieAdapter(getActivity(), R.layout.grid_movie_item, movieData);
//Get a reference to the gridView and attach the adapter to it
GridView mGridView = (GridView) rootView.findViewById(R.id.gridView);
mGridView.setAdapter(mMovieAdapter);
}
首先更改Asynctask的参数
public class FetchMovieTask extends AsyncTask<Void, String[], String[]> {}
了解参数和返回类型的流程
更新:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.gird_layout, container, false);
//Initialize our array adapter
mMovieData = new ArrayList<>();
updateView(mMovieData);
return rootView;
}
void updateView(ArrayList<>() movieData){
mMovieAdapter = new MovieAdapter(getActivity(), R.layout.grid_movie_item, movieData);
//Get a reference to the gridView and attach the adapter to it
GridView mGridView = (GridView) rootView.findViewById(R.id.gridView);
mGridView.setAdapter(mMovieAdapter);
}
首先要做的是编译代码?据我所知,您的AsyncTask具有以下签名-
public class FetchMovieTask extends AsyncTask<String[], Void, Void> {
公共类FetchMovieTask扩展异步任务{
但是您正在从doInBackground
返回字符串[],这在理想情况下会给您一个错误。
无论如何,在您的情况下,您不必从AsyncTask返回任何内容。只需在onPostExecute
-mMovieAdapter.setMovieData(Arrays.asList(result))
顺便说一句,类型结果应该是String[],而不是我看到的String。首先要做的是编译代码?从我看到的情况来看,AsyncTask具有以下签名-
public class FetchMovieTask extends AsyncTask<String[], Void, Void> {
公共类FetchMovieTask扩展异步任务{
但是您正在从doInBackground
返回字符串[],这在理想情况下会给您一个错误。
无论如何,在您的情况下,您不必从AsyncTask返回任何内容。只需在onPostExecute
-mMovieAdapter.setMovieData(Arrays.asList(result))
顺便说一句,类型结果应该是String[]而不是我所看到的字符串。谢谢!这就是我感到困惑的原因。我已经有了一个名为get-getMovieJson的方法,该方法将项目添加到模型中,然后由适配器处理。doInBackground返回Json原始字符串,然后将其发送到getMovieJson。它确实运行了,并且在它之前膨胀了一个gridView项目崩溃。我不知道如何在onPostExecute中实现此适配器,我将编辑我的代码,请参见上文,谢谢!。因此,既然我的doInbackground只返回原始JSON字符串,那么参数仍然会是吗?因为JSON是一个字符串数组。那么你应该将签名更改为-
,我已经尝试过了。另外请参阅我对Sadiq提供的答案的评论。这解释了我想要完成的任务。我还更新了上面的代码。很抱歉,如果我在尝试提出解决方案时没有提供太多帮助,我会像你所看到的那样,完全卡在异步任务上。哈哈。谢谢!这就是为什么我感到困惑的原因。我已经有了一个名为get的方法getMovieJson,将项目添加到模型中,然后由适配器处理。doInBackground返回Json原始字符串,然后将其发送到getMovieJson。它确实运行了,并在崩溃之前膨胀了一个gridView项目。我不知道如何在onPostExecute中实现此适配器。我将编辑我的代码,请参见上文anks!。既然我的doInbackground只返回原始JSON字符串,那么参数还会是吗?因为JSON是一个字符串数组。那么你应该将签名更改为-
,我已经尝试过了。另外,请参阅我对Sadiq提供的答案的评论。这解释了我想要完成的任务。我还更新了d上面的代码。很抱歉,如果我在试图想出一个解决方案时帮不了什么忙,我完全被困在异步任务上了,你可以看到哈哈。使用箭头的解释很好谢谢你的回答,这个话题仍然让人困惑,但你已经消除了我的一些疑问。我真的很感谢你的回答。你得到了哪一部分您是否感到困惑?我已修复了您方法的返回类型。尽管您可以更改其他部分以获得所需类型的实际结果。您好,再次感谢您花时间回答。我已尝试修复我的参数。我已更新了上面的代码。我对AsyncTask要求我的ArrayAdapter膨胀什么感到困惑在onPostExecute方法上,我必须检查是否有视图,以便循环使用视图,而不会影响性能。我将调用mMovieAdapter.setMovieData(mMovieData)我该怎么做?我想我必须返回我的适配器,以便在onPostExecute中检查它?我不能将rootView放在updateView和充气器中。使用箭头的解释很好谢谢你的回答,这个话题仍然令人困惑,但你已经消除了我的一些疑问。我非常感谢你的回答ponses。您对哪一部分感到困惑?我已修复了方法的返回类型。尽管您可以更改其他部分以获得所需类型的实际结果。您好,再次感谢您花时间回答。我已尝试修复我的参数。我已更新了上面的代码。我对AsyncTask的要求感到困惑我的ArrayAdapter用于膨胀视图。在onPostExecute方法上,我必须检查是否有视图,以便循环使用视图,而不会影响性能。我将调用mMovieAdapter.setMovieData(mMovieData)我该怎么做呢?我想我必须返回我的适配器才能在onPostExecute中检查它?我不能将rootView放在u
@Override
protected ArrayList<Movies> doInBackground(Object... params) {}
private ArrayList<Movies> getMovieJson(String movieJsonStr) throws JSONException {
....
mMovieData.add(movieItem);
return mMovieData;
}
@Override
protected void onPostExecute(ArrayList<Movies> movieData){
updateView(movieData);
}
public class FetchMovieTask extends AsyncTask<String[], Void, Void> {