ViewPager中的Android Parcel

时间:2013-09-23 13:10:00

标签: android serialization android-fragments android-viewpager parcelable

我在我的应用中使用ViewPager,当我在与home button的互动过程中按ViewPager时,应用程序崩溃了,我得到了error

3780-3780/? E/AndroidRuntime: FATAL EXCEPTION: main
    java.lang.RuntimeException: Parcel: unable to marshal value OrdinaryFragment{42000b70 #0 id=0x7f090005 android:switcher:2131296261:0}
    at android.os.Parcel.writeValue(Parcel.java:1235)
    at android.os.Parcel.writeList(Parcel.java:622)
    at android.os.Parcel.writeValue(Parcel.java:1195)
    at android.os.Parcel.writeMapInternal(Parcel.java:591)
    at android.os.Bundle.writeToParcel(Bundle.java:1619)
    at android.os.Parcel.writeBundle(Parcel.java:605)
    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2245)
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:2912)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4895)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
    at dalvik.system.NativeStart.main(Native Method)

我知道有一些序列化问题,但我不知道为什么会遇到这个问题。

这是我的代码:

ViewPager:

public class ViewPagerActivity extends FragmentActivity {

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link android.support.v4.view.ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

/**
 * DBManager Class for comunicating with DataBase
 */
private DBManager dbManager;

/**
 * Fragment ArrayList for ViewPager's adapter input
 */
private ArrayList<Fragment> adapterList;
private ArrayList<String> sectionTitleList;
private long recId;
private MasterDataWithRecIdI masterData;
private static final int NEW_RECORD = -1;
private static final String LAYOUT_ID = "LayoutId";
private static final int NUMBER_OF_PAGES = 5;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    dbManager = new DBManager();

    masterData = (MasterDataWithRecIdI) getIntent().getSerializableExtra("MasterData");

    if(savedInstanceState != null) {
        ArrayList<Fragment> savedList = (ArrayList<Fragment>) savedInstanceState.getSerializable("Adapter");
        initFragments(masterData, savedList);
    }else{
        initFragments(masterData, null);
    }

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);
    mViewPager.setOffscreenPageLimit(mSectionsPagerAdapter.getCount());
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("Adapter", adapterList);
}

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

/**
 * Initializing Fragments and SectionsPagerAdapter
 */
private void initFragments(MasterDataWithRecIdI masterData, ArrayList<Fragment> savedAdapter) {
    instantiateTitleArray();
    if(savedAdapter == null){
        adapterList = new ArrayList<Fragment>();
        Fragment fm;
        Bundle bundle;

        int layoutId = 0;
        for (int i = 0; i < 3; i++) {
            switch(i) {
                case 0:
                    layoutId = R.layout.client_information_page;
                    break;
                case 1:
                    layoutId = R.layout.loan_information_page;
                    break;
                case 2:
                    layoutId = R.layout.additional_information_1_page;
                    break;
            }
            bundle = new Bundle();
            bundle.putInt(LAYOUT_ID, layoutId);
            fm = new OrdinaryFragment();
            fm.setArguments(bundle);
            adapterList.add(fm);
        }

        fm = new LastFragment();
        adapterList.add(fm);

        recId = NEW_RECORD;
        if (masterData != null) {
            recId = masterData.getRecId();
        }
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), adapterList, sectionTitleList, recId, dbManager);
        ((LastFragment) fm).setSectionsPagerAdapter(mSectionsPagerAdapter, dbManager);
    } else {
        recId = NEW_RECORD;
        if (masterData != null) {
            recId = masterData.getRecId();
        }
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(), savedAdapter, sectionTitleList, recId, dbManager);
    }
}

OrdinaryFragment:

public class OrdinaryFragment extends Fragment {
private static final String LAYOUT_ID = "LayoutId";
private int layoutId;

/**
 * The fragment argument representing the section number for this
 * fragment.
 */
public static final String ARG_SECTION_NUMBER = "section_number";


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    this.setRetainInstance(true);
    layoutId = getArguments().getInt(LAYOUT_ID);

    View rootView = inflater.inflate(layoutId, container, false);

    ArrayList<DetailsItemI> list = (ArrayList<DetailsItemI>)getArguments().getSerializable("ViewData");
    ViewFillerController viewFiller = new ViewFillerController();
    viewFiller.fillTheView(rootView, list);

    return rootView;
}

}

SectionsPagerAdapter:

public class SectionsPagerAdapter extends FragmentPagerAdapter implements Serializable{

private static final int NEW_RECORD = -1;
private ArrayList<Fragment> fragmentList;
private ArrayList<String> sectionTitleList;
private long recId;
private DBManager dbManager;

public SectionsPagerAdapter(FragmentManager fm, ArrayList<Fragment> fragmentList, ArrayList<String> sectionTitleList, long recId, DBManager dbManager) {
    super(fm);
    this.fragmentList = fragmentList;
    this.sectionTitleList = sectionTitleList;
    this.recId = recId;
    this.dbManager = dbManager;
}

@Override
public Fragment getItem(int position) {
    // getItem is called to instantiate the fragment for the given page.
    // Return a OrdinaryFragment (defined as a static inner class
    // below) with the page number as its lone argument.

    Fragment fragment = this.fragmentList.get(position);
    Bundle args;
    if (fragment.getArguments() == null) {
        args = new Bundle();
    }else{
        args = fragment.getArguments();
    }
    args.putInt(OrdinaryFragment.ARG_SECTION_NUMBER, position + 1);
    args.putLong("RecordID", recId);
    if(recId != NEW_RECORD){
        args.putSerializable("ViewData", getTabViewValues(recId, position));
    }
    if(fragment.getArguments() == null) {
        fragment.setArguments(args);
    }
    return fragment;
}

private ArrayList<DetailsItemI> getTabViewValues(long recId, int tabId){
    return dbManager.selectDetailsWithRecIdAndTabId(recId, tabId);
}

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

@Override
public CharSequence getPageTitle(int position) {
    Locale l = Locale.getDefault();
    if(sectionTitleList == null){
        return "";
    }
    return this.sectionTitleList.get(position).toUpperCase(l);
}

}

Custom TextView我使用Parcelable

public class XTextView extends TextView {
private String viewParameter;

public XTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    getViewAttributes(context, attrs);
}

public String getXViewParameter(){
    return String.valueOf(this.viewParameter);
}

public String getXValue(){
    return String.valueOf(this.getText());
}

public void setXValue(String xValue) {
    this.setText(xValue);
}

/**
 * Getting all attributes of view Id-s.
 *
 * @param context
 * @param attrs
 */
private void getViewAttributes(Context context, AttributeSet attrs) {
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.XTextView);
    final int N = a.getIndexCount();
    for(int i = 0; i < N; i++){
        int attr = a.getIndex(i);
        switch(attr){
            case R.styleable.XTextView_viewParameter:
                viewParameter = a.getString(attr);
                break;
        }
    }
    a.recycle();
}

@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    SavedStateTextView ss = new SavedStateTextView(superState);
    ss.stateToSave = String.valueOf(this.getText().toString());

    return ss;
}

@Override
public void onRestoreInstanceState(Parcelable state) {
    if(!(state instanceof SavedStateTextView)) {
        super.onRestoreInstanceState(state);
        return;
    }
    SavedStateTextView ss = (SavedStateTextView) state;
    super.onRestoreInstanceState(ss.getSuperState());
    this.setText(ss.stateToSave);
}

}

SavedStateTextView类:

public class SavedStateTextView extends View.BaseSavedState {
String stateToSave;

public SavedStateTextView(Parcelable superState) {
    super(superState);
}

private SavedStateTextView(Parcel in) {
    super(in);
    this.stateToSave = in.readString();
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    super.writeToParcel(dest, flags);
    dest.writeString(this.stateToSave);
}

public static final Parcelable.Creator<SavedStateTextView> CREATOR =
        new Parcelable.Creator<SavedStateTextView>() {
            @Override
            public SavedStateTextView createFromParcel(Parcel source) {
                return new SavedStateTextView(source);
            }

            @Override
            public SavedStateTextView[] newArray(int size) {
                return new SavedStateTextView[size];
            }
        };

}

我希望能有所帮助。

提前致谢。

已解决

见下面的答案。

1 个答案:

答案 0 :(得分:0)

我解决了我的问题。

我在Fragments中使用的ViewPager不是Serializable。我刚刚让它们实现Serializable Interface,现在它可以正常工作。