Fireprufe15
Fireprufe15

Reputation: 249

Viewpager with data from asynctask

So I am making an app which pulls a story from a server. The story arrives split into parts. I want to put each story part on a different ViewPager page, but what I've tried so far either makes the app crash or just gives me a blank screen.

This is my code for that activity:

package com.firegaming.myfirstapp;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Parcelable;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class ContinueStoryActivity extends FragmentActivity {


private ProgressDialog pDialog;
JSONParser jsonParser = new JSONParser();
private static int partCounter;
private static String storyID;
ArrayList<String> storyPartList = new ArrayList<>();
FragmentStatePagerAdapter adapter;
ViewPager pager;
JSONArray parts = null;

private static final String GET_STORY_URL = "http://firegaming.host56.com/get_story.php";
private static final String TAG_SUCCESS = "success";
private static final String TAG_MESSAGE = "message";
private static final String TAG_PARTS = "parts";
private static final String TAG_PARTCOUNT = "partCount";
private static final String TAG_STORYID = "storyID";
private static final String TAG_STORYTEXT = "storyText";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_continue_story);


    pager = (ViewPager) findViewById(R.id.pager);
    adapter = new MyPagerAdapter(getSupportFragmentManager());
    pager.setAdapter(adapter);

    new GetStory().execute();

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_continue_story, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

public class MyPagerAdapter extends FragmentStatePagerAdapter {

    public MyPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int pos) {
        return StoryFragment.newInstance(storyPartList.get(pos).toString());
    }

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

    public int getItemPosition(Object object){
        return POSITION_NONE;
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
        //do nothing here! no call to super.restoreState(arg0, arg1);
    }
}



    class GetStory extends AsyncTask<String, String, String>{

    @Override
    protected void onPreExecute(){
        super.onPreExecute();
        pDialog = new ProgressDialog(ContinueStoryActivity.this);
        pDialog.setMessage("Getting Story...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    @Override
    protected String doInBackground(String... args){
        int success;
        try{

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("username", MainActivity.USERNAME));

            Log.d("Request!", "Starting!");

            JSONObject json = jsonParser.makeHttpRequest(GET_STORY_URL, "GET", params);

            Log.d("Story Attempt", json.toString());
            success = json.getInt(TAG_SUCCESS);
            if (success == 1){

                parts = json.getJSONArray(TAG_PARTS);
                partCounter = Integer.parseInt(json.getString(TAG_PARTCOUNT));
                storyID = json.getString(TAG_STORYID);
                return json.getString(TAG_SUCCESS);

            } else {

                Log.d("Story Get Failure!", json.getString(TAG_MESSAGE));
                return json.getString(TAG_MESSAGE);
            }

        } catch (JSONException ex){
            ex.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String file_url) {

        pDialog.dismiss();

        if (file_url != null) {
            try {
                for (int i = 0; i < parts.length(); i++) {
                    JSONObject c = parts.getJSONObject(i);
                    int id = c.getInt(TAG_STORYID);
                    String storyText = c.getString(TAG_STORYTEXT);
                    storyPartList.add(id-1, storyText);
                }
            } catch (JSONException ex) {
                ex.printStackTrace();
            }

            adapter.notifyDataSetChanged();

        }

    }

}


}

What am I doing wrong here?

EDIT: When not returning null, as was suggested, the app crashes again. These are all the errors that come up in logcat when the app crashes.

01-03 12:29:19.298  29861-29861/com.firegaming.myfirstapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.firegaming.myfirstapp, PID: 29861
java.lang.NullPointerException
        at com.firegaming.myfirstapp.ContinueStoryActivity$MyPagerAdapter.getItem(ContinueStoryActivity.java:88)
        at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:105)
        at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:837)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:987)
        at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
        at android.support.v4.view.ViewPager.setAdapter(ViewPager.java:447)
        at com.firegaming.myfirstapp.ContinueStoryActivity$GetStory.onPostExecute(ContinueStoryActivity.java:163)
        at com.firegaming.myfirstapp.ContinueStoryActivity$GetStory.onPostExecute(ContinueStoryActivity.java:99)
        at android.os.AsyncTask.finish(AsyncTask.java:632)
        at android.os.AsyncTask.access$600(AsyncTask.java:177)
        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:136)
        at android.app.ActivityThread.main(ActivityThread.java:5586)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
        at dalvik.system.NativeStart.main(Native Method)

Upvotes: 1

Views: 2137

Answers (2)

Yash Sampat
Yash Sampat

Reputation: 30611

Assuming that all is well with your web service and you're parsing the data correctly, add the following code to your MyPagerAdapter class:

@Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
        //do nothing here! no call to super.restoreState(arg0, arg1);
}

First try this and see if it works ... also please post the logcat of your crash.

Three more things you need to ensure:

  1. Make sure that the android.support.v4.app.Fragment and android.app.Fragment classes are not used together. Use everything from the v4 support library only.

  2. Make sure that getCount() returns the actual number of fragments corresponding to your getItem(int index) method: use storyPartList.size() in getCount().

  3. As cYrixmorten has suggested, make storyPartList an ArrayList and call storyPartList.add(...) instead of storyPartList.put(...).

Upvotes: 0

cYrixmorten
cYrixmorten

Reputation: 7108

I have a list of suggestions:

I am suspicious of the fact that storyPartList is a hasmap with id's dictated be the incoming data. If the incoming id's for instance is [0,2,3] then getItem(1) will fail. What happens if you let storyPartListsimply be an arraylist (as the name sort of suggests that it is)?

The getCount of adapter is similarly dictated by the incoming data:

@Override
public int getCount() {
    return partCounter;
}

Instead let the counter depend on the actual size of storyPartList:

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

Now, having the pager data being determined purely by the amount of data added to storyPartList, I would suggest creating the pager once in onCreate() instead of re-creating it each time you add a story:

ViewPager pager;
FragmentStatePagerAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_continue_story);
    new GetStory().execute();

    pager = (ViewPager) findViewById(R.id.pager);
    adapter = new MyPagerAdapter(getSupportFragmentManager())
    pager.setAdapter(adapter);
}

And in onPostExecute now simply do:

adapter.notifyDataSetChanged();

This will make the adapter refresh it's contents based on the content of storyPartList. To make the adapter update correctly you might have to add this to MyPagerAdapter:

public int getItemPosition(Object object){
     return POSITION_NONE;
}

Summary of suggestions

  • Make storyPartList be a List instead of Map
  • Let getCount return storyPartList.size()
  • Create the pager in onCreate and call notifyDataSetChanged when adding a story
  • Finally implement getItemPosition in the adapter to make it update correctly

Upvotes: 2

Related Questions