Android 片段改变方向和 NullPointerException
Android fragment change orientation and NullPointerException
我尝试在片段上创建应用程序,但出现一些错误:
FATAL EXCEPTION: main Process: pl.pionas.zabawa, PID: 3074
java.lang.NullPointerException
at pl.pionas.zabawa.Fragments.HomeFragment.initializeListViewPromo(HomeFragment.java:77)
at pl.pionas.zabawa.Fragments.HomeFragment.OnTaskCompletedArticlesPromo(HomeFragment.java:71)
at pl.pionas.zabawa.AsyncTasks.ArticlesPromoAsyncTask.onResponse(ArticlesPromoAsyncTask.java:70)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
此错误是在我更改 class 片段(示例转到 LoginFragment.class)和方向时出现的。
我的MainMenuActivity.class:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawer;
private Toolbar toolbar;
private NavigationView nvDrawer;
private ActionBarDrawerToggle drawerToggle;
private Fragment fragment = null;
private Boolean restore = false;
private String mTitle;
FragmentManager fragmentManager;
private Boolean action = false;
String tag = null;
private int prev;
private ArrayList<MenuFragment> mapMenu = new ArrayList<MenuFragment>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
if (savedInstanceState != null) {
fragment = fragmentManager.getFragment(savedInstanceState, "currentFragment");
restore = savedInstanceState.getBoolean("restore");
mTitle = savedInstanceState.getString("mTitle");
mapMenu = savedInstanceState.getParcelableArrayList("mapMenu");
tag = fragment.getTag();
} else {
fragment = new HomeFragment();
mapMenu.add(new MenuFragment(getString(R.string.app_name), 0));
restore = false;
mTitle = getString(R.string.app_name);
tag = mTitle;
}
if (fragment != null) {
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
if (restore) {
fragmentManager.findFragmentByTag(tag);
} else {
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
}
}
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(mTitle);
// Find our drawer view
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.drawer_open, R.string.drawer_close);
// Tie DrawerLayout events to the ActionBarToggle
mDrawer.addDrawerListener(drawerToggle);
nvDrawer = (NavigationView) findViewById(R.id.nvView);
View headerLayout = nvDrawer.inflateHeaderView(R.layout.nav_header);
// We can now look up items within the header if needed
ImageView ivHeaderPhoto = (ImageView) headerLayout.findViewById(R.id.imageView);
Drawable myDrawable = ResourcesCompat.getDrawable(getResources(), R.drawable.logo, null);
ivHeaderPhoto.setImageDrawable(myDrawable);
// Setup drawer view
setupDrawerContent(nvDrawer);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
switch (item.getItemId()) {
case android.R.id.home:
mDrawer.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
// `onPostCreate` called when activity start-up is complete after `onStart()`
// NOTE! Make sure to override the method with only a single `Bundle` argument
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
drawerToggle.onConfigurationChanged(newConfig);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem) {
int menuId = menuItem.getItemId();
if (prev == menuId) {
mDrawer.closeDrawers();
return;
}
prev = menuId;
createNewFragment(menuId, true);
}
private void createNewFragment(int menuId, boolean add) { // Create a new fragment and specify the fragment to show based on nav item clicked
Class fragmentClass;
action = true;
int position = 0;
switch (menuId) {
case R.id.nav_login:
fragmentClass = LoginFragment.class;
mTitle = getString(R.string.menu_login);
position = 1;
break;
case R.id.nav_articles:
fragmentClass = CategoryFragment.class;
mTitle = getString(R.string.menu_articles);
position = 2;
break;
default:
fragmentClass = HomeFragment.class;
mTitle = APP_NAME;
break;
}
if (add) {
mapMenu.add(new MenuFragment(mTitle, menuId));
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
tag = mTitle;
if (action) {
// Insert the fragment by replacing any existing fragment
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
// Highlight the selected item has been done by NavigationView
nvDrawer.getMenu().getItem(position).setChecked(true);
}
// Set action bar title
getSupportActionBar().setTitle(mTitle);
// Close the navigation drawer
mDrawer.closeDrawers();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("restore", true);
outState.putParcelableArrayList("mapMenu", mapMenu);
outState.putString("mTitle", getSupportActionBar().getTitle().toString());
getSupportFragmentManager().putFragment(outState, "currentFragment", fragment);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
int i = mapMenu.size();
if (i > 1) {
mapMenu.remove(i - 1);
MenuFragment menuFragment = mapMenu.get((i - 2));
tag = menuFragment.getTitle();
createNewFragment(menuFragment.getMenuPosition(), false);
} else {
MainActivity.this.finish();
}
}
} }
我的HomeFragment.class:
public class HomeFragment extends Fragment implements OnTaskCompletedArticlesLastAdded {
private ListView listViewLastAdded;
private ArrayList<Article> articleLastAddedList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArticlesLastAddedAsyncTask articlesLastAddedAsyncTask = new ArticlesLastAddedAsyncTask(getContext(), this);
articlesLastAddedAsyncTask.execute();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
listViewLastAdded = (ListView) rootView.findViewById(R.id.listViewLastAdded);
return rootView;
}
@Override
public void OnTaskCompletedArticlesLastAdded(ArrayList<Article> articleList) {
articleLastAddedList = articleList;
initializeListLastAdded();
}
private void initializeListLastAdded() {
ArticlesListAdapter adapter = new ArticlesListAdapter(getContext(), articleLastAddedList);
listViewLastAdded.setAdapter(adapter);
}
}
我做错了什么?
感谢您的帮助。
如果您不希望 Android 在屏幕旋转时重新启动 activity(这会破坏您的片段并导致 NULLPointer 异常),您可以添加
android:configChanges="orientation|screenSize"
在您 Androidmanifest.xml
的 activity 标签内
我尝试在片段上创建应用程序,但出现一些错误:
FATAL EXCEPTION: main Process: pl.pionas.zabawa, PID: 3074 java.lang.NullPointerException at pl.pionas.zabawa.Fragments.HomeFragment.initializeListViewPromo(HomeFragment.java:77) at pl.pionas.zabawa.Fragments.HomeFragment.OnTaskCompletedArticlesPromo(HomeFragment.java:71) at pl.pionas.zabawa.AsyncTasks.ArticlesPromoAsyncTask.onResponse(ArticlesPromoAsyncTask.java:70) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall.run(ExecutorCallAdapterFactory.java:68) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5017) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) at dalvik.system.NativeStart.main(Native Method)
此错误是在我更改 class 片段(示例转到 LoginFragment.class)和方向时出现的。
我的MainMenuActivity.class:
public class MainActivity extends AppCompatActivity {
private DrawerLayout mDrawer;
private Toolbar toolbar;
private NavigationView nvDrawer;
private ActionBarDrawerToggle drawerToggle;
private Fragment fragment = null;
private Boolean restore = false;
private String mTitle;
FragmentManager fragmentManager;
private Boolean action = false;
String tag = null;
private int prev;
private ArrayList<MenuFragment> mapMenu = new ArrayList<MenuFragment>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
if (savedInstanceState != null) {
fragment = fragmentManager.getFragment(savedInstanceState, "currentFragment");
restore = savedInstanceState.getBoolean("restore");
mTitle = savedInstanceState.getString("mTitle");
mapMenu = savedInstanceState.getParcelableArrayList("mapMenu");
tag = fragment.getTag();
} else {
fragment = new HomeFragment();
mapMenu.add(new MenuFragment(getString(R.string.app_name), 0));
restore = false;
mTitle = getString(R.string.app_name);
tag = mTitle;
}
if (fragment != null) {
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
if (restore) {
fragmentManager.findFragmentByTag(tag);
} else {
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
}
}
// Set a Toolbar to replace the ActionBar.
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(mTitle);
// Find our drawer view
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerToggle = new ActionBarDrawerToggle(this, mDrawer, toolbar, R.string.drawer_open, R.string.drawer_close);
// Tie DrawerLayout events to the ActionBarToggle
mDrawer.addDrawerListener(drawerToggle);
nvDrawer = (NavigationView) findViewById(R.id.nvView);
View headerLayout = nvDrawer.inflateHeaderView(R.layout.nav_header);
// We can now look up items within the header if needed
ImageView ivHeaderPhoto = (ImageView) headerLayout.findViewById(R.id.imageView);
Drawable myDrawable = ResourcesCompat.getDrawable(getResources(), R.drawable.logo, null);
ivHeaderPhoto.setImageDrawable(myDrawable);
// Setup drawer view
setupDrawerContent(nvDrawer);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// The action bar home/up action should open or close the drawer.
switch (item.getItemId()) {
case android.R.id.home:
mDrawer.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
// `onPostCreate` called when activity start-up is complete after `onStart()`
// NOTE! Make sure to override the method with only a single `Bundle` argument
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
drawerToggle.onConfigurationChanged(newConfig);
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem) {
int menuId = menuItem.getItemId();
if (prev == menuId) {
mDrawer.closeDrawers();
return;
}
prev = menuId;
createNewFragment(menuId, true);
}
private void createNewFragment(int menuId, boolean add) { // Create a new fragment and specify the fragment to show based on nav item clicked
Class fragmentClass;
action = true;
int position = 0;
switch (menuId) {
case R.id.nav_login:
fragmentClass = LoginFragment.class;
mTitle = getString(R.string.menu_login);
position = 1;
break;
case R.id.nav_articles:
fragmentClass = CategoryFragment.class;
mTitle = getString(R.string.menu_articles);
position = 2;
break;
default:
fragmentClass = HomeFragment.class;
mTitle = APP_NAME;
break;
}
if (add) {
mapMenu.add(new MenuFragment(mTitle, menuId));
}
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
tag = mTitle;
if (action) {
// Insert the fragment by replacing any existing fragment
fragmentManager.beginTransaction().replace(R.id.flContent, fragment, tag).addToBackStack(tag).commit();
// Highlight the selected item has been done by NavigationView
nvDrawer.getMenu().getItem(position).setChecked(true);
}
// Set action bar title
getSupportActionBar().setTitle(mTitle);
// Close the navigation drawer
mDrawer.closeDrawers();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("restore", true);
outState.putParcelableArrayList("mapMenu", mapMenu);
outState.putString("mTitle", getSupportActionBar().getTitle().toString());
getSupportFragmentManager().putFragment(outState, "currentFragment", fragment);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
int i = mapMenu.size();
if (i > 1) {
mapMenu.remove(i - 1);
MenuFragment menuFragment = mapMenu.get((i - 2));
tag = menuFragment.getTitle();
createNewFragment(menuFragment.getMenuPosition(), false);
} else {
MainActivity.this.finish();
}
}
} }
我的HomeFragment.class:
public class HomeFragment extends Fragment implements OnTaskCompletedArticlesLastAdded {
private ListView listViewLastAdded;
private ArrayList<Article> articleLastAddedList;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArticlesLastAddedAsyncTask articlesLastAddedAsyncTask = new ArticlesLastAddedAsyncTask(getContext(), this);
articlesLastAddedAsyncTask.execute();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
listViewLastAdded = (ListView) rootView.findViewById(R.id.listViewLastAdded);
return rootView;
}
@Override
public void OnTaskCompletedArticlesLastAdded(ArrayList<Article> articleList) {
articleLastAddedList = articleList;
initializeListLastAdded();
}
private void initializeListLastAdded() {
ArticlesListAdapter adapter = new ArticlesListAdapter(getContext(), articleLastAddedList);
listViewLastAdded.setAdapter(adapter);
}
}
我做错了什么? 感谢您的帮助。
如果您不希望 Android 在屏幕旋转时重新启动 activity(这会破坏您的片段并导致 NULLPointer 异常),您可以添加
android:configChanges="orientation|screenSize"
在您 Androidmanifest.xml
的 activity 标签内