Android:FragmentStatePagerAdapter活动已经被破坏 - 向上或向后导航

时间:2012-12-06 22:03:34

标签: android android-fragments android-viewpager android-tabs

我正在使用游标加载器在活动中创建选项卡。我正在使用可浏览的标签,详见android View Pager文档 http://developer.android.com/reference/android/support/v4/view/ViewPager.html

到目前为止,我还没有实现将我的任何页面加载到后台堆栈,因此当我单击它时会跳转到上一个活动。 (现在这很好。)单击后退或上移按钮会导致运行时异常java.lang.RuntimeException: Unable to destroy activity: java.lang.IllegalStateException: Activity has been destroyed

我所知道的与示例之间的唯一区别是使用游标,并且该示例将ViewPager本身设置为内容视图,而我使用了包含ViewPager的布局文件。我也使用FragmentStatePagerAdapter而不是FragmentPagerAdapter,但在这两者之间切换没有任何区别。

我不确定android onDestroy调用中的内容会尝试两次破坏活动。我的代码如下。任何帮助表示赞赏,我很乐意提供更多信息。感谢。

public class WorksheetActivity extends FragmentActivity implements android.support.v4.app.LoaderManager.LoaderCallbacks<Cursor> {
public String user;
private static final int DAY_LOADER = 0;
public int program_index;
public int program_id;
public int item_id;
public int type_key;
ViewPager mViewPager;
TabsAdapter mTabsAdapter;
LoaderManager.LoaderCallbacks<Cursor> mCallbacks;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_worksheet);
    mCallbacks = this;
    ActionBar bar = getActionBar();
    //this sets up to include tabs, and to show the title on each tab
    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
    //enables navigation up, when clicked calls on options item selected for home button. 
    bar.setDisplayHomeAsUpEnabled(true);
    Bundle extras = getIntent().getExtras();
    if (!(extras.isEmpty())){
        user = extras.getString("user");
        //used for moving up to the Program Activity and restoring the selection. 
        program_index = extras.getInt(ProgramActivity.PROGRAM_KEY);
        program_id = extras.getInt(ProgramActivity.PROGRAM_ID);
        item_id = extras.getInt(ProgramActivity.ITEM_ID);
        type_key = extras.getInt(ProgramActivity.TYPE_KEY);
    }
    Bundle tabData = new Bundle();
    tabData.putAll((extras.isEmpty()? savedInstanceState : extras));
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mTabsAdapter = new TabsAdapter(this, mViewPager, null, tabData);
    LoaderManager lm = getSupportLoaderManager();
    lm.initLoader(0, tabData, mCallbacks);

}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_worksheet, menu);
    return true;
}

@Override
public void onSaveInstanceState(Bundle out){
    out.putString("user",user);
    //used for moving up to the Program Activity and restoring the selection. 
    out.putInt(ProgramActivity.PROGRAM_KEY, program_index);
    out.putInt(ProgramActivity.ITEM_ID, item_id);
    out.putInt(ProgramActivity.PROGRAM_ID, program_id);
    out.putInt(ProgramActivity.TYPE_KEY, type_key);
}

@Override
public void onRestoreInstanceState(Bundle in){
    user = in.getString("user");
    program_index = in.getInt(ProgramActivity.PROGRAM_KEY);
    program_id = in.getInt(ProgramActivity.PROGRAM_ID);
    item_id = in.getInt(ProgramActivity.ITEM_ID);
    type_key = in.getInt(ProgramActivity.TYPE_KEY);
}

@SuppressLint("NewApi")
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            Intent upIntent = new Intent(this, ProgramActivity.class);
            upIntent.putExtra("user", user);
            upIntent.putExtra(ProgramActivity.PROGRAM_KEY, program_index);
            if (NavUtils.shouldUpRecreateTask(this, upIntent)){
                TaskStackBuilder.create(this)
                    .addNextIntent(new Intent(this, Marta_QC.class))
                    .addNextIntent(upIntent).startActivities();
                finish();
            }else{
                NavUtils.navigateUpTo(this, upIntent);
            }
            return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle arg1) {
    CursorLoader cl = null;
    switch(id){
        case DAY_LOADER:
            cl = new CursorLoader(getApplicationContext(), Tasks.CONTENT_URI, new String[]{Tasks.DAY_COL},Tasks.PROGRAM_COL+" = ?",
                                    new String[]{Integer.toString(program_id)}, Tasks.DAY_COL+" ASC");
            break;
        default:
    }
    return cl;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor c) {
    switch(loader.getId()){
        case DAY_LOADER:
            mTabsAdapter.swapCursor(c);
            break;
        default:
    }
}

@Override
public void onLoaderReset(Loader<Cursor> loader) {
    switch(loader.getId()){
    case DAY_LOADER:
        mTabsAdapter.swapCursor(null);
        break;
    default:
}

}

public static class TabsAdapter extends FragmentStatePagerAdapter
    implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
    private final Context mContext;
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
    private Bundle mArgs;
    private int currentPosition;

    static final class TabInfo{
        private final Class<?> clss;
        private final Bundle args;
        public final int position;
        TabInfo(Class<?> _class, Bundle _args, int _position){
            clss = _class;
            args = _args;
            position = _position;
        }
    }

    public TabsAdapter (FragmentActivity activity, ViewPager pager, Cursor days, Bundle args){
        super(activity.getSupportFragmentManager());
        mContext = activity;
        mActionBar = activity.getActionBar();
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
        mArgs = args;
    }

    public void swapCursor(Cursor c){
        mActionBar.removeAllTabs();
        mViewPager.removeAllViews();
        //add the exceptions tab.  Always first.
        ActionBar.Tab tab = mActionBar.newTab();
        Bundle tabArgs = new Bundle();
        tabArgs.putAll(mArgs);
        this.addTab(tab, ExceptionsSheet.class, tabArgs);

        //add each of the day tabs to the set, which stores unique values only
        LinkedHashSet<String> days = new LinkedHashSet<String>();
        if(c.moveToFirst()){
            do{
                days.add(c.getString(c.getColumnIndex(Tasks.DAY_COL)));
            }while (c.moveToNext());
        }
        //iterate through the unique days
        for(String day:days){
            ActionBar.Tab dayTab = mActionBar.newTab();
            Bundle dayArgs = new Bundle();
            dayArgs.putAll(mArgs);
            dayArgs.putString("day", day);
            this.addTab(dayTab, Worksheet.class, dayArgs);
        }
        //start with the first day
        mActionBar.setSelectedNavigationItem(1);
    }

    public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args){
        //implemented adding a position to the tab info class.  
        //gets the current tab count prior to adding this tab. 
        TabInfo info = new TabInfo(clss, args, this.getCount());
        tab.setTag(info);
        tab.setTabListener(this);
        mTabs.add(info);
        if (clss.equals(ExceptionsSheet.class)){
            //tab.setCustomView(R.layout.exceptions_tab);
            tab.setText(mContext.getText(R.string.exceptions_tab_title));
        }else{
            if(clss.equals(Worksheet.class)){
                tab.setText("Day "+args.getString("day"));
            }else{
                Log.d("unknown class", clss.toString());
            }

        }
        mActionBar.addTab(tab);
        notifyDataSetChanged(); 
    }

    @Override
    public void onPageSelected(int pos) {
        // set the tab to match the page, following a swipe action.
        currentPosition = pos;
        mActionBar.setSelectedNavigationItem(pos);
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        //this will return our tab info
        TabInfo minfo = (TabInfo) tab.getTag();
        int pos = minfo.position;
        this.getItem(currentPosition);
        mViewPager.setCurrentItem(pos);
        currentPosition = pos;  
    }

    //this is the FragmentPager Adapter main method
    //here we will use the arguments bundled into the tab to set the
    //fragment for the page. 
    @Override
    public Fragment getItem(int pos) {
        TabInfo tabInfo = mTabs.get(pos);
        return Fragment.instantiate(mContext, tabInfo.clss.getName(), tabInfo.args);
    }


}




//class for exceptions display
public static class ExceptionsSheet extends Fragment{

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        int i = 1;
        i = i+1;
        //must include false, since we're attaching to the ViewPager sheet, not the root view.
        return inflater.inflate(R.layout.exception, container, false);
    }
}

//class for standard worksheet display
public static class Worksheet extends Fragment{
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){

        return inflater.inflate(R.layout.worksheet, container, false);
    }

}

}

1 个答案:

答案 0 :(得分:0)

我发现了问题。销毁Activity时,将调用onLoaderReset()方法。在这里,我交换了一个空游标来删除对游标的引用(与非自定义适配器一样),但是我的swapCursor方法没有检查游标是否为null。一旦我解决了这个问题,代码就会在活动被销毁后不再尝试更新UI。