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 标签内