0

I am developing a MovieApp which loads movie posters in MainActivity Fragment using AsyncTask background thread. I am using gridview and BaseAdapter to display images. Following is the code.

MainActivityFragment.java :

package com.android.example.cinemaapp.app;
import android.app.Fragment;
import android.content.Intent;
import android.content.SharedPreferences; 
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
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.AdapterView;
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.io.Serializable;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;


public class MainActivityFragment extends Fragment{

MoviePosterAdapter moviePosterAdapter;
GridView posterGridView;
public HashMap<String, JSONObject> movieMap;

public MainActivityFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setHasOptionsMenu(true);
}

@Override
public void onStart(){
    super.onStart();
    updateMovies();
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.moviefragment, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_refresh) {
        updateMovies();
    }
    return super.onOptionsItemSelected(item);
}

public void updateMovies(){
    SharedPreferences sharedPreferences =    PreferenceManager.getDefaultSharedPreferences(getActivity());
    String sortBy = sharedPreferences.getString(getString(R.string.pref_sort_key), getString(R.string.pref_sort_popular));
    new FetchMoviePosterTask().execute(sortBy);
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    moviePosterAdapter = new MoviePosterAdapter(getActivity());
    posterGridView = (GridView) rootView.findViewById(R.id.gridview_movie);
    posterGridView.setAdapter(moviePosterAdapter);
    posterGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
            // logic to start detail activity
            startActivity(intent);
        }
    });
   return rootView;
}

public class FetchMoviePosterTask extends AsyncTask<String, String, Void> implements Serializable {


    @Override
    protected Void doInBackground(String... params) {
        Log.v("FetchMoviePosterTask", "In background method");

        HttpURLConnection urlConnection = null;
        BufferedReader reader = null;

        String movieJsonStr;

        try {

            //logic to create uri builder

            URL url = new URL(builtUri.toString());

            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.
                movieJsonStr = null;
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while ((line = reader.readLine()) != null) {
                buffer.append(line + "\n");
            }

            if (buffer.length() == 0) {
                movieJsonStr = null;
            }
            movieJsonStr = buffer.toString();
            // Log.v("MainActivityFragment", "Movie json "+movieJsonStr);

            try {
                String[] posterPaths = getPosterPaths(movieJsonStr);
                for(String path : posterPaths){
                    publishProgress(path);
                }
            }catch(JSONException je){
                Log.e("MoviePosterPath","Error while parsing JSON");
            }
        } catch (IOException e) {
            Log.e("MoviePosterAdapter", "Error ", e);
            movieJsonStr = null;
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (final IOException e) {
                    Log.e("MoviePosterAdapter", "Error closing stream", e);
                }
            }
        }
       return null;
    }

    public String[] getPosterPaths(String movieJsonStr) throws JSONException{
        final String POSTER_PATH = //some value
        final String POSTER_SIZE = //some value
        JSONObject jsonObject = new JSONObject(movieJsonStr);
        JSONArray results = jsonObject.getJSONArray("results");
        String[] posterStrs = new String[results.length()];
        movieMap = new HashMap<String, JSONObject>();

        for(int i =0; i < results.length(); i++){
            JSONObject movieObj = (JSONObject) results.get(i);
            posterStrs[i] = POSTER_PATH + POSTER_SIZE + movieObj.getString("poster_path");
            movieMap.put(posterStrs[i], movieObj);
        }

        return posterStrs;
    }

    @Override
    protected void onProgressUpdate(String... posterValues){
        Log.v("FetchMoviePosterTask", "In onProgress method");
        moviePosterAdapter.add(posterValues[0]);
        super.onProgressUpdate(posterValues);
    }

    @Override
    protected void onPostExecute(Void result) {
        Log.v("FetchMoviePosterTask", "In onPostExecute method");
        moviePosterAdapter.notifyDataSetChanged();
        super.onPostExecute(result);
    }
}
}

MoviePosterAdapter.java :

package com.android.example.cinemaapp.app;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

import com.squareup.picasso.Picasso;

import java.util.ArrayList;


public class MoviePosterAdapter extends BaseAdapter {

ArrayList<String> movieArray = new ArrayList<String>();
private Context mContext;

public MoviePosterAdapter(Context c) {
    mContext = c;
}

void add(String path){
    movieArray.add(path);
}

void clear(){
    movieArray.clear();
}

void remove(int index){
    movieArray.remove(index);
}

@Override
public int getCount() {
    return movieArray.size();
}

@Override
public Object getItem(int position) {
    return movieArray.get(position);
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView;
    if (convertView == null) {
        // if it's not recycled, initialize some attributes
        imageView = new ImageView(mContext);

        imageView.setScaleType(ImageView.ScaleType.FIT_XY);

    } else {
        imageView = (ImageView) convertView;
    }

    Picasso.with(mContext).load(movieArray.get(position)).into(imageView);
    return imageView;
}
}

Problem : When the application is first launched, UI is not getting populated with imageviews. In Logcat I could see control is flowing through doBackground(), onProgressUpdate() and onPostExecute().

When I click 'Refresh' button or If i navigate to some other activity or app and return to Movie app UI (onResume()) it is working perfectly fine. Images are displayed.

Many thanks in advance!

Viv
  • 15
  • 6
  • 1
    You're wrong about the lifecycle- going to another app and coming back doesn't just call onResume, it calls onStart then onResume. The app is stopped (onStop is called) whenever it goes totally off screen. onStart is called whenever the app is reactivated from a stopped state. – Gabe Sechan Apr 08 '16 at 10:24
  • Agreed.. but why it is not called when app is first launched. I also tried by calling updateMovies() from onCreateView() , it is not working still. – Viv Apr 08 '16 at 11:53

2 Answers2

0

You should change updateMovies(); from onStart() to onCreateView. As Gabe Sechan said, you're wrong about the lifecycle. Try to do some research on the Fragment lifecycle.

António Paulo
  • 351
  • 3
  • 18
0

Just you need to call method updateMovies(); from onCreateView() after posterGridView = (GridView) rootView.findViewById(R.id.gridview_movie);

remove call from start();

Keyur Android
  • 375
  • 2
  • 6
  • 20