如何使用API​​中的数据填充Gridview?

时间:2016-05-17 13:37:39

标签: android gridview android-asynctask

我正在尝试构建下一个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后到达但我无法“通知”视图“嘿,你有一些数据可以处理”。

提前致谢,请原谅我的英语。

1 个答案:

答案 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);
        }
    }
    ...
}