这可能是一个冗长的帖子,所以我提前道歉.
我正在使用主/详细信息流来显示项目列表,单击它时会打开详细信息视图.这些项目是从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对我也完全没问题).我有点绝望,我一直在寻找解决方案太久了.
非常感谢您的帮助.
最佳答案