Как использовать навигатор в нескольких действиях

Я хочу определить один ящик навигации, который я могу использовать во всем приложении. Я следовал инструкциям выбранного ответа здесь в качестве своего первого подхода: Тот же навигационный ящик в разных действиях

Я сделал несколько изменений, а именно вызов onCreateDrawer из переопределенного onCreate. Я обновил свою последующую деятельность, чтобы расширить DashboardActivity ( "базовая активность" из примера). Когда я запускаю свое второе действие, я получаю исключение с нулевым указателем, жалуясь, что пользовательский интерфейс навигации не существует, когда onCreateDrawer пытается установить переключатель, прослушиваемый в ящике.

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.DrawerLayout.setDrawerListener(android.support.v4.widget.DrawerLayout$DrawerListener)' on a null object reference

Вот базовая (приборная панель) и последующая (логарифмическая тренировка) активность - спросите, есть ли другой код, который вы хотите увидеть. Код для пользовательского интерфейса ящика и связанной с ним деятельности - это то, что вышло из окна при создании нового Nav Drawer Activity в Android Studio.

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

        onCreateDrawer();

        Realm realm = Realm.getDefaultInstance();

        RealmQuery<Exercise> query = realm.where(Exercise.class);
        RealmResults<Exercise> result = query.findAll();
        Log.d(TAG, "There are " + result.size() + " exercises ready for use.");

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent logWorkoutIntent = new Intent(getApplicationContext(), LogWorkoutActivity.class);
                startActivity(logWorkoutIntent);
            }
        });

        //TODO: Remove this sign out button
        Button signOutButton = (Button) findViewById(R.id.button_sign_out);
        signOutButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FirebaseAuth.getInstance().signOut();
                Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
                startActivity(intent);
                Toast.makeText(getApplicationContext(), "Signed out", Toast.LENGTH_LONG).show();
            }
        });

        //TODO: Remove this data tester
        updateUserName();
    }

    //@Override
    protected void onCreateDrawer() {
        Log.d(TAG, "onCreateDrawer called");
        //super.onCreate(savedInstanceState);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        mDrawerLayout.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

...

-

LogWorkoutActivity.java
public class LogWorkoutActivity extends DashboardActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_log_workout);
        setContentView(R.layout.activity_log_workout);
        super.onCreateDrawer();
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        //getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

}

Ответ 1

Я думаю, что вам не хватает ящика с id drawer_layout в макете activity_log_workout.

Для того, чтобы этот подход работал, вы должны иметь DrawerLayout с id drawer_layout во всех ваших макетах действий, которые должны иметь ящик.

Я также заметил что-то своеобразное с вашим кодом. В каждом действии, которое продолжается DashboardActivity, вы сначала устанавливаете setContentView(R.id.activity_dashboard), затем вызываете onCreateDrawer(), затем вы меняете представление содержимого и снова создаете ящик. Я думаю, что это очень субоптимальный подход.

Я предлагаю вам создать класс BaseDrawerActivity, чтобы инкапсулировать создание ящика и логику привязки UI. Затем вы просто расширяете его в тех случаях, когда вам нужен ящик. Вы можете сделать это следующим образом:

public abstract class BaseDrawerActivity extends AppCompatActivity {

    // move all your drawer related fields here

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

        setContentView(getLayoutResId());

        // the same method you have right now
        onCreateDrawer();
    }


    /*
     * Extending activities use this class to supply the 
     * id of their layout file. This way you can set the view 
     * only once and there is no need to create the drawer twice.
     */
    @LayoutResId
    public abstract int getLayoutResId();

}