我正在尝试构建下一个Android应用程序:
1)连接到“电影数据库”API并带上热门电影的JSON。
2)从JSON中提取所有流行电影海报(小图片)的链接。
3)使用Picasso库将图像放在Gridview上。
步骤1和2工作正常。 3几乎就在那里,但我的工作的异步类型有问题。
如果我对海报应该对女巫进行硬编码,那么Gridview就可以正常填充,但如果我通过后台工作完成,我认为在数据准备好之前以及来自API的数据是准备好视图不会得到它或不呈现它。因此,活动看起来空白。
MainFragment.java
package com.example.android.popmovies;
import android.content.Context;
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.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
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;
import java.util.List;
public class MainFragment extends Fragment {
// the array to populate with data from the API
private List moviesArray= new ArrayList();
public MainFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Connection connection = new Connection();
connection.execute();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
GridView gridView = (GridView) rootView.findViewById(R.id.grid_view_id);
gridView.setAdapter(new CustomAdapter(this.getContext(), moviesArray));
return rootView;
}
public class CustomAdapter extends BaseAdapter{
private Context context;
private List items;
public CustomAdapter(Context context, List items){
super();
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override public View getView(int position, View convertView, ViewGroup parent) {
ImageView img;
if (convertView == null) {
img = new ImageView(context);
img.setPadding(0,5,0,0);
convertView = img;
} else {
img = (ImageView) convertView;
}
Picasso.with(context)
.load((String) items.get(position))
.into(img);
return convertView;
}
}
public class Connection extends AsyncTask<Void, Void, String[]> {
private final String LOG_TAG = Connection.class.getSimpleName();
private String[] getPosterDataFromJson(String moviesJsonStr) throws JSONException {
String[] posters = new String[moviesJsonStr.length()];
// These are the names of the JSON objects that need to be extracted
final String RESULTS = "results";
//
// convertimos el JSON en un array
JSONObject moviesJson = new JSONObject(moviesJsonStr);
JSONArray moviesArray = moviesJson.getJSONArray(RESULTS);
for(int i = 0; i < moviesArray.length(); i++) {
String image;
JSONObject poster = moviesArray.getJSONObject(i);
image = poster.getString("poster_path");
posters[i] = image;
}
return posters;
}
@Override
protected String[] doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String moviesJsonStr;
try {
// Construct the URL
String baseUrl = "http://api.themoviedb.org/3/movie/popular";
String apiKey = "?api_key=" + BuildConfig.POP_MOVIES_API_KEY;
URL url = new URL(baseUrl.concat(apiKey));
// Create the request 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.
return 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.
return null;
}
// Paso todo el JSON a una variable
moviesJsonStr = buffer.toString();
// Extraigo del JSON lo que me interesa y lo guardo en un vector
String[] datos = getPosterDataFromJson(moviesJsonStr);
// Verificamos que haya algo en el vector
//Log.v(LOG_TAG, "Estoy en CONNECTION y el tamaño de DATOS es: " + Integer.toString(datos.length));
for (int i=0; i<datos.length; i++){
while(datos[i] != null){
Log.v(LOG_TAG, datos[i]);
break;
}
}
return datos;
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
return null;
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return null;
}
@Override
protected void onPostExecute(String[] result) {
if (result != null) {
for(String posterStrings : result) {
while(posterStrings != null){
String direccion = "http://image.tmdb.org/t/p/" + "w185/" + posterStrings;
Log.v(LOG_TAG, direccion);
moviesArray.add(direccion);
break;
}
}
}
}
}
}
我几乎确信问题是数据在创建View后到达但我无法“通知”视图“嘿,你有一些数据可以处理”。
提前致谢,请原谅我的英语。
答案 0 :(得分:2)
您需要通知适配器有关更新的项目列表。在您的适配器中添加类似updateMovies方法的内容,并从onPostExecute中调用它。 像那样:
CustomAdapter mAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
...
mAdapter = new CustomAdapter(this.getContext(), moviesArray);
gridView.setAdapter(mAdapter);
...
}
public class CustomAdapter extends BaseAdapter{
...
public void updateMovies(List items) {
mItems = items;
notifyDataSetChanged();
}
...
}
public class Connection extends AsyncTask<Void, Void, String[]> {
...
@Override
protected void onPostExecute(String[] result) {
if (result != null) {
for(String posterStrings : result) {
while(posterStrings != null){
String direccion = "http://image.tmdb.org/t/p/" + "w185/" + posterStrings;
Log.v(LOG_TAG, direccion);
moviesArray.add(direccion);
break;
}
}
mAdapter.updateMovies(moviesArray);
}
}
...
}