单击操作栏中的“向上”时,主/详细信息流中的空意图(空指针异常)

多米尼克

这可能是一篇冗长的文章,所以我提前致歉。

我正在使用主数据/明细流显示项目列表,单击它会打开明细视图。这些项目是从Web服务加载的。它在带有碎片的平板电脑上效果很好,但在手机上却不断崩溃。它可以正确显示项目详细信息(CheatViewPageIndicator.java),但是当我使用操作栏中左上方的“向上”按钮返回到父活动(CheatListActivity.java)时,应用程序会崩溃,并出现nullpointer异常。我认为我是在错误的位置从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 ArrayList<Cheat>();

                        if (cheats != null) {
                            for (int j = 0; j < cheats.length; j++) {
                                cheatsArrayList.add(cheats[j]);
                            }
                        } else {
                            Log.e("CheatListActivity()", "Webservice.getCheatList() == null");
                        }

                        for (int i = 0; i < cheats.length; i++) {
                            Log.d("cheats", cheats[i].getCheatTitle());
                        }

                        gameObj.setCheats(cheats);

                        // Put game object to local storage for large games like
                        // Pokemon
                        editor.putString(Konstanten.PREFERENCES_TEMP_GAME_OBJECT_VIEW, new Gson().toJson(gameObj));
                        editor.commit();
                    } else {
                        Log.e("CheatTitleList:getCheats()", "No Network");
                        Toast.makeText(CheatListActivity.this, R.string.no_internet, Toast.LENGTH_SHORT).show();
                    }

                } catch (Exception ex) {
                    Log.e(getClass().getName(), "Error executing getCheats()", ex);
                }
            }
        }).start();

    }

    public Cheat[] getCheatsForFragment(final Intent intent) {

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

                if (cheats != null) {
                    for (int j = 0; j < cheats.length; j++) {
                        cheatsArrayList.add(cheats[j]);
                    }
                } else {
                    Log.e("CheatListActivity()", "Webservice.getCheatList() == null");
                }

                for (int i = 0; i < cheats.length; i++) {
                    Log.d("cheats", cheats[i].getCheatTitle());
                }

                gameObj.setCheats(cheats);

                // Put game object to local storage for large games like Pokemon
                editor.putString(Konstanten.PREFERENCES_TEMP_GAME_OBJECT_VIEW, new Gson().toJson(gameObj));
                editor.commit();
            } else {
                Log.e("CheatTitleList:getCheats()", "No Network");
                Toast.makeText(this, R.string.no_internet, Toast.LENGTH_SHORT).show();
            }

        } catch (Exception ex) {
            Log.e(getClass().getName(), "Error executing getCheats()", ex);
        }

        return cheats;
    }

    /**
     * Callback method from {@link CheatListFragment.Callbacks} indicating that
     * the item with the given ID was selected.
     */
    @Override
    public void onItemSelected(int id) {
        if (mTwoPane) {
            // In two-pane mode, show the detail view in this activity by
            // adding or replacing the detail fragment using a
            // fragment transaction.

            visibleCheat = cheats[id];

            cheatForumFragment = new CheatForumFragment();
            cheatDetailMetaFragment = 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);

        }
    }   
}

以及listview的片段。

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 AsyncTask<Game, Void, Void> {

        @Override
        protected Void doInBackground(Game... params) {

            if (params[0].getCheats() == null) {
                cheats = cheatListActivity.getCheatsForFragment(cheatListActivity.getIntent()); 
            } else {
                cheats = params[0].getCheats();
            }

            for (int i = 0; i < cheats.length; i++) {
                Log.d("Cheat Item ", cheats[i].getCheatTitle());
                cheatsArrayList.add(cheats[i]);
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            cheatAdapter = new CheatAdapter(getActivity(), R.layout.cheatlist_item, cheatsArrayList);
            setListAdapter(cheatAdapter);
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // Restore the previously 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<Cheat> {

        private final ArrayList<Cheat> items;

        public CheatAdapter(Context context, int textViewResourceId, ArrayList<Cheat> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.cheatlist_item, null);
            }

            try {
                Cheat cheat = items.get(position);
                if (cheat != null) {

                    TextView tt = (TextView) v.findViewById(R.id.game_title);
                    tt.setText(cheat.getCheatTitle());
                    tt.setTypeface(fontRoboto);

                    // Durchschnittsrating (nicht Member-Rating)
                    RatingBar ratingBar = (RatingBar) v.findViewById(R.id.small_ratingbar);
                    ratingBar.setNumStars(5);
                    ratingBar.setRating(cheat.getRatingAverage() / 2);

                    ImageView flag_newaddition = (ImageView) v.findViewById(R.id.newaddition);
                    if (cheat.getDayAge() < Konstanten.CHEAT_DAY_AGE_SHOW_NEWADDITION_ICON) {
                        flag_newaddition.setImageResource(R.drawable.flag_new);
                        flag_newaddition.setVisibility(View.VISIBLE);
                    } else {
                        flag_newaddition.setVisibility(View.GONE);
                    }

                    ImageView flag_screenshots = (ImageView) v.findViewById(R.id.screenshots);
                    if (cheat.isScreenshots()) {
                        flag_screenshots.setVisibility(View.VISIBLE);
                        flag_screenshots.setImageResource(R.drawable.flag_img);
                    } else {
                        flag_screenshots.setVisibility(View.GONE);
                    }

                    ImageView flag_german = (ImageView) v.findViewById(R.id.flag);
                    if (cheat.getLanguageId() == 2) { // 2 = Deutsch
                        flag_german.setVisibility(View.VISIBLE);
                        flag_german.setImageResource(R.drawable.flag_german);
                    } else {
                        flag_german.setVisibility(View.GONE);
                    }

                }
            } catch (Exception e) {
                Log.e(getClass().getName() + ".getView ERROR:", e.getMessage());
            }
            return v;
        }
    }
}

两窗格模式下的局部视图(在平板电脑上):

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, null), 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);    

返回时似乎“意图”为空。我想知道为什么会这样?我需要怎么做才能保持数据意图?(或者任何其他解决方法,如何摆脱nullpointer对我来说也很好)。我有点绝望,我一直在寻找解决方案太久了。

非常感谢您的帮助。

德米德

我几乎可以肯定问题出onOptionsItemSelected()CheatViewPageIndicator您不需要在那里开始新的活动,在主从模式中,一次总是有一个相同的活动。只有片段在变化。

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

处理主/详细信息流中的菜单项的正确方法是什么?

来自分类Dev

具有主/详细信息流的fragablelistview片段

来自分类Dev

处理主/详细信息流中的菜单项的正确方法是什么?

来自分类Dev

单击主详细信息页面中的项目时如何防止打开多个页面?

来自分类Dev

启动意图时出现空指针异常

来自分类Dev

Ios 中的主详细信息页面

来自分类Dev

当详细信息为空时,不会显示空表单

来自分类Dev

获取 TFS 构建详细信息时出现空引用异常

来自分类Dev

操作栏上的空指针异常

来自分类Dev

单击按钮时出现空指针异常

来自分类Dev

动作栏中的微调器结果为空指针异常

来自分类Dev

片段中的工具栏不断抛出空指针异常

来自分类Dev

Android中的空指针异常

来自分类Dev

片段中的空指针异常

来自分类Dev

GoogleMap中的空指针异常

来自分类Dev

String []中的空指针异常

来自分类Dev

片段中的空指针异常

来自分类Dev

JDBC中的空指针异常

来自分类Dev

OnOptionItemSelected中的空指针异常

来自分类Dev

OnClickListener中的空指针异常

来自分类Dev

DataAdapter 中的空指针异常

来自分类Dev

TestNG中的空指针异常

来自分类Dev

HashMap 中的空指针异常

来自分类Dev

主详细信息页面-Android中的显示菜单图标

来自分类Dev

Delphi XE2中的FastReport主/详细信息

来自分类Dev

Delphi XE2中的FastReport主/详细信息

来自分类Dev

主详细信息页面-Android中的显示菜单图标

来自分类Dev

xamarin.forms 中的主详细信息页面

来自分类Dev

我在主详细信息页面中收到错误消息