android – 在操作栏中单击“向上”时主/详细流程中的空意图(nullpointer异常)

前端之家收集整理的这篇文章主要介绍了android – 在操作栏中单击“向上”时主/详细流程中的空意图(nullpointer异常)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这可能是一个冗长的帖子,所以我提前道歉.

我正在使用主/详细信息流来显示项目列表,单击它时会打开详细信息视图.这些项目是从Web服务加载的.
它可以在平板电脑上使用碎片很好用,但在手机上却不断崩溃.它可以正确显示项目详细信息(CheatViewPageIndicator.java)但是当我使用操作栏左上角的“向上”按钮返回到父活动(CheatListActivity.java)时,应用程序会一直崩溃并出现空指针异常.我想我正在从错误的位置加载来自Web服务的数据,这就是它崩溃的原因.我打算在这里编写我的代码,希望有人可以给我一个建议,我将如何以正确的方式做到这一点.

(我已经修改了一些类来缩短帖子.)

“主”活动:

public class CheatListActivity extends FragmentActivity implements CheatListFragment.Callbacks,ReportCheatDialogListener,RateCheatDialogListener {

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

        settings = getSharedPreferences(Konstanten.PREFERENCES_FILE,0);
        editor = settings.edit();

        cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 

        cheatProgressDialog = ProgressDialog.show(this,getString(R.string.please_wait) + "...",getString(R.string.retrieving_data) + "...",true);

        handleIntent(getIntent());

        if (findViewById(R.id.cheat_detail_container) != null) {
            // The detail container view will be present only in the
            // large-screen layouts (res/values-large and
            // res/values-sw600dp). If this view is present,then the
            // activity should be in two-pane mode.
            mTwoPane = true;

            // In two-pane mode,list items should be given the
            // 'activated' state when touched.
            ((CheatListFragment) getSupportFragmentManager().findFragmentById(R.id.cheat_list)).setActivateOnItemClick(true);
        }
        cheatProgressDialog.dismiss();
        // TODO: If exposing deep links into your app,handle intents here.

    }

    private void handleIntent(final Intent intent) {

        new Thread(new Runnable() {

            @Override
            public void run() {
                gameObj = new Gson().fromJson(intent.getStringExtra("gameObj"),Game.class);

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        getActionBar().setDisplayHomeAsUpEnabled(true);
                        getActionBar().setTitle(gameObj.getGameName());
                        getActionBar().setSubtitle(gameObj.getSystemName());
                    }

                });
                try {
                    if (cm.getActiveNetworkInfo() != null) {
                        if (member == null) {
                            cheats = Webservice.getCheatList(gameObj,0);
                        } else {
                            cheats = Webservice.getCheatList(gameObj,member.getMid());
                        }
                        cheatsArrayList = new ArrayListMetaFragment = new CheatDetailMetaFragment();

            // VIEW FOR TABLETS
            Bundle arguments = new Bundle();
            arguments.putInt(CheatDetailTabletFragment.ARG_ITEM_ID,id);
            arguments.putString("cheatObj",new Gson().toJson(cheats[id]));
            arguments.putString("cheatForumFragment",new Gson().toJson(cheatForumFragment));
            arguments.putString("cheatDetailMetaFragment",new Gson().toJson(cheatDetailMetaFragment));

            cheatDetailFragment = new CheatDetailTabletFragment();
            cheatDetailFragment.setArguments(arguments);
            getSupportFragmentManager().beginTransaction().replace(R.id.cheat_detail_container,cheatDetailFragment).commit();

        } else {
            // In single-pane mode,simply start the detail activity
            // for the selected item ID.
            // Intent detailIntent = new Intent(this,YyyDetailActivity.class);
            // detailIntent.putExtra(YyyDetailFragment.ARG_ITEM_ID,id);
            // startActivity(detailIntent);

            editor.putInt(Konstanten.PREFERENCES_PAGE_SELECTED,id);
            editor.commit();

            // Using local Preferences to pass data for large game objects
            // (instead of intent) such as Pokemon
            Intent explicitIntent = new Intent(CheatListActivity.this,CheatViewPageIndicator.class);
            explicitIntent.putExtra("selectedPage",id);
            explicitIntent.putExtra("layoutResourceId",R.layout.activity_cheatview_pager);
            explicitIntent.putExtra("pageIndicatorColor",Konstanten.CYAN_DARK);
            startActivity(explicitIntent);

        }
    }   
}

列表视图的片段.

public class CheatListFragment extends ListFragment {

    /**
     * The serialization (saved instance state) Bundle key representing the
     * activated item position. Only used on tablets.
     */
    private static final String STATE_ACTIVATED_POSITION = "activated_position";

    /**
     * The fragment's current callback object,which is notified of list item
     * clicks.
     */
    private Callbacks mCallbacks = sDummyCallbacks;

    /**
     * The current activated item position. Only used on tablets.
     */
    private int mActivatedPosition = ListView.INVALID_POSITION;

    /**
     * A callback interface that all activities containing this fragment must
     * implement. This mechanism allows activities to be notified of item
     * selections.
     */
    public interface Callbacks {
        /**
         * Callback for when an item has been selected.
         */
        public void onItemSelected(int position);
    }

    /**
     * A dummy implementation of the {@link Callbacks} interface that does
     * nothing. Used only when this fragment is not attached to an activity.
     */
    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(int id) {
        }
    };


    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public CheatListFragment() {
    }

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

        cheatListActivity = (CheatListActivity) getActivity();
        fontRoboto = Tools.getFontRobotoRegular(getActivity().getAssets());

        settings = cheatListActivity.getSharedPreferences(Konstanten.PREFERENCES_FILE,0);

        gameObj = new Gson().fromJson(settings.getString(Konstanten.PREFERENCES_TEMP_GAME_OBJECT_VIEW,null),Game.class);

        if( gameObj == null) {
            new GetCheatsTask().execute(new Game());            
        } else {
            new GetCheatsTask().execute(gameObj);           
        }
    }

    private class GetCheatsTask extends AsyncTaskIoUsly serialized activated item position.
        if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
            setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
        }
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Activities containing this fragment must implement its callbacks.
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }

        mCallbacks = (Callbacks) activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();

        // Reset the active callbacks interface to the dummy implementation.
        mCallbacks = sDummyCallbacks;
    }

    @Override
    public void onListItemClick(ListView listView,View view,int position,long id) {
        super.onListItemClick(listView,view,position,id);

        // Notify the active callbacks interface (the activity,if the
        // fragment is attached to one) that an item has been selected.
        // mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
        mCallbacks.onItemSelected(position);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mActivatedPosition != ListView.INVALID_POSITION) {
            // Serialize and persist the activated item position.
            outState.putInt(STATE_ACTIVATED_POSITION,mActivatedPosition);
        }
    }

    /**
     * Turns on activate-on-click mode. When this mode is on,list items will be
     * given the 'activated' state when touched.
     */
    public void setActivateOnItemClick(boolean activateOnItemClick) {
        // When setting CHOICE_MODE_SINGLE,ListView will automatically
        // give items the 'activated' state when touched.
        getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
    }

    private void setActivatedPosition(int position) {
        if (position == ListView.INVALID_POSITION) {
            getListView().setItemChecked(mActivatedPosition,false);
        } else {
            getListView().setItemChecked(position,true);
        }

        mActivatedPosition = position;
    }

    private class CheatAdapter extends ArrayAdapter

双窗格模式下的详细视图(在平板电脑上):

public class CheatDetailTabletFragment extends Fragment implements OnClickListener {
    /**
     * The fragment argument representing the item ID that this fragment
     * represents.
     */
    public static final String ARG_ITEM_ID = "item_id";

    /**
     * The dummy content this fragment is presenting.
     */
    private CheatContent.CheatItem mItem;
    private View rootView;

    /**
     * Mandatory empty constructor for the fragment manager to instantiate the
     * fragment (e.g. upon screen orientation changes).
     */
    public CheatDetailTabletFragment() {
    }

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

        ca = (CheatListActivity) getActivity();

        cheatTitleTypeface = Tools.getFontRobotoThin(getActivity().getAssets());
        cheatTextTypeface = Tools.getFontRobotoRegular(getActivity().getAssets());

        settings = getActivity().getSharedPreferences(Konstanten.PREFERENCES_FILE,0);
        editor = settings.edit();

        if (getArguments().containsKey(ARG_ITEM_ID)) {
            // Load the dummy content specified by the fragment
            // arguments. In a real-world scenario,use a Loader
            // to load content from a content provider.

            mItem = CheatContent.ITEM_MAP.get(getArguments().getInt(ARG_ITEM_ID));
            cheatObj = new Gson().fromJson(getArguments().getString("cheatObj"),Cheat.class);

            cheatForumFragment = new Gson().fromJson(getArguments().getString("cheatForumFragment"),CheatForumFragment.class);
            cheatDetailMetaFragment = new Gson().fromJson(getArguments().getString("cheatDetailMetaFragment"),CheatDetailMetaFragment.class);
        }

    }

    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_cheat_detail,container,false);

        // ...

        // Show the dummy content as text in a TextView.
        if (mItem != null) {
            ((TextView) rootView.findViewById(R.id.text_cheat_before_table)).setText(mItem.getCheatTitle());
            ((TextView) rootView.findViewById(R.id.text_cheat_title)).setText(mItem.getCheatId());
        }

        // ...

        populateView();         

        return rootView;
    }

    /**
     * Create Layout
     */
    private void populateView() {
        // fills the view. no problems here.
    }

    /**
     * Populate Table Layout
     */
    private void fillTableContent() {
        // filling table content here. no problems here.
    }

    private void fillSimpleContent() {
        // filling with other content. works fine,too.
    }

}

单窗格模式下的详细信息视图(在电话上):

public class CheatViewPageIndicator extends FragmentActivity implements ReportCheatDialogListener,RateCheatDialogListener {

    // define variables...

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        LayoutInflater inflater = LayoutInflater.from(this);
        intent = getIntent();

        viewLayout = inflater.inflate(intent.getIntExtra("layoutResourceId",R.layout.activity_cheatview_pager),null);
        setContentView(viewLayout);

        settings = getSharedPreferences(Konstanten.PREFERENCES_FILE,0);
        editor = settings.edit();

        getActionBar().setHomeButtonEnabled(true);
        getActionBar().setDisplayHomeAsUpEnabled(true);

        try {
            gameObj = new Gson().fromJson(settings.getString(Konstanten.PREFERENCES_TEMP_GAME_OBJECT_VIEW,Game.class);
            if (gameObj == null) {
                gameObj = new Gson().fromJson(intent.getStringExtra("gameObj"),Game.class);
            }
            editor.putString(Konstanten.PREFERENCES_TEMP_GAME_OBJECT_VIEW,new Gson().toJson(gameObj));
            editor.commit();

            pageSelected = intent.getIntExtra("selectedPage",0);
            activePage = pageSelected;
            pageIndicatorColor = intent.getIntExtra("pageIndicatorColor",Konstanten.CYAN_DARK);
            cheatObj = gameObj.getCheats();
            visibleCheat = cheatObj[pageSelected];

            getActionBar().setTitle(gameObj.getGameName());
            getActionBar().setSubtitle(gameObj.getSystemName());

            initialisePaging();
        } catch (Exception e) {
            Log.e(CheatViewPageIndicator.class.getName(),e.getMessage() + "");
        }

    }

    private void initialisePaging() {
        // ...
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.handset_cheatview_menu,menu);

        // Search
        getMenuInflater().inflate(R.menu.search_menu,menu);

        // Associate searchable configuration with the SearchView
        SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
        SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
        searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));

        return super.onCreateOptionsMenu(menu);
    }



    @Override
    protected void onResume() {
        super.onResume();
        invalidateOptionsMenu();
    }

    public ConnectivityManager getConnectivityManager() {
        if (cm == null) {
            cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        }
        return cm;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            // This ID represents the Home or Up button. In the case of this
            // activity,the Up button is shown. Use NavUtils to allow users
            // to navigate up one level in the application structure. For
            // more details,see the Navigation pattern on Android Design:
            //
            // http://developer.android.com/design/patterns/navigation.html#up-vs-back

            // onBackPressed();
            // return true;

            Intent upIntent = new Intent(this,CheatListActivity.class);
            NavUtils.getParentActivityIntent(this);
            if (NavUtils.shouldUpRecreateTask(this,upIntent)) {
                // This activity is NOT part of this app's task,so create a new
                // task when navigating up,with a synthesized back stack.
                TaskStackBuilder.create(this)
                // Add all of this activity's parents to the back stack
                        .addNextIntentWithParentStack(upIntent)
                        // Navigate up to the closest parent
                        .startActivities();
            } else {
                // This activity is part of this app's task,so simply
                // navigate up to the logical parent activity.
                // NavUtils.navigateUpTo(this,upIntent);
                upIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(upIntent);
                finish();
            }
            return true;
        }
        return super.onOptionsItemSelected(item);

    }       

}   

因此,在单窗格模式(在手机上),当我从CheatViewPageIndicator.java单击操作栏中的“向上”按钮以获取CheatListActivity.java时,我得到一个指向此行的nullpointer异常:

gameObj = new Gson().fromJson(intent.getStringExtra("gameObj"),Game.class);    

回来时似乎“intent”为null.我想知道为什么会这样?我需要做什么才能将数据保存在意图中? (或任何其他解决方案如何摆脱nullpointer对我也完全没问题).我有点绝望,我一直在寻找解决方案太久了.

非常感谢您的帮助.

最佳答案
我几乎可以肯定问题来自CheatViewPageIndicator中的onOptionsItemSelected().您不需要在那里开始新的活动,在主 – 细节模式中,一次总是有一个相同的活动.只有片段在变化.

要提供正确使用“向上”按钮的功能,您应该在添加片段时调用fragmentTransaction.addToBackStack(null). Android将自行处理所有堆栈逻辑.在android.R.id.home中根本不做任何事情,你不需要它.

猜你在找的Android相关文章