Viewpager与来自asynctask的数据

时间:2015-01-03 10:11:50

标签: java android android-asynctask android-viewpager

所以我正在创建一个从服务器中提取故事的应用程序。故事分为几部分。我想将每个故事部分放在一个不同的ViewPager页面上,但到目前为止我尝试过的任何一个都会导致应用程序崩溃或只是给我一个空白屏幕。

这是我的活动代码:

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();

        }

    }

}


}

我在这里做错了什么?

编辑: 当没有返回null时,如建议的那样,应用程序再次崩溃。 这些是应用程序崩溃时logcat中出现的所有错误。

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)

2 个答案:

答案 0 :(得分:2)

我有一系列建议:

我怀疑storyPartList是一个带有id的hasmap的传入数据。如果传入的id例如是[0,2,3],则getItem(1)将失败。如果你让storyPartLists只是一个arraylist会发生什么(顾名思义就是这样)?

适配器的getCount同样由传入数据决定:

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

相反,让计数器取决于storyPartList的实际大小:

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

现在,将寻呼机数据完全根据添加到storyPartList的数据量来确定,我建议在onCreate()中创建一次寻呼机,而不是每次添加故事时重新创建寻呼机:

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);
}

现在只需onPostExecute

adapter.notifyDataSetChanged();

这将使适配器根据storyPartList的内容刷新其内容。要正确更新适配器,您可能需要将其添加到MyPagerAdapter

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

建议摘要

  • 将storyPartList设为List而不是Map
  • 让getCount返回storyPartList.size()
  • 在onCreate中创建寻呼机,并在添加故事时调用notifyDataSetChanged
  • 最后在适配器中实现getItemPosition以使其正确更新

答案 1 :(得分:0)

假设您的网络服务一切正常并且您正确解析数据,请将以下代码添加到MyPagerAdapter类:

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

首先尝试一下,看看它是否有效......也请发布崩溃的logcat。

还需要确保三件事:

  1. 确保未同时使用android.support.v4.app.Fragmentandroid.app.Fragment类。仅使用v4支持库中的所有内容。

  2. 确保getCount()返回与您的getItem(int index)方法相对应的实际片段数:在storyPartList.size()中使用getCount()

  3. 根据cYrixmorten建议,将storyPartList设为ArrayList并致电storyPartList.add(...)而不是storyPartList.put(...)