简体   繁体   中英

How to use the navigation drawer menu without loading it each time?

This is more of a Java question (having some trouble understanding how should the inheritance be set). I'm trying to add a side menu to my application (which works ok). The class signature of my menu activity is:

public class MenuActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener

Once the user logged in, the first window he see is the main dashboard. The dashboard activity extends the menu activity in order to have the side menu:

public class DashboardActivity extends MenuActivity 

For navigating to other activities, I implemented the onNavigationItemSelected method to select the intent to load (The method is located in the MenuActivity ):

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    if (toggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Intent intent = null;
        switch (item.getItemId()) {
            case R.id.lay_dashboard:
                intent = new Intent(this, DashboardActivity.class);
                //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                break;
            case R.id.lay_settings:
                intent = new Intent(this, SettingsActivity.class);
                //intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                break;
            case R.id.lay_contacts:
                startActivity(new Intent(this, ContactsActivity.class));
                break;
            case R.id.lay_about:
                startActivity(new Intent(this, AboutActivity.class));
                break;
            case R.id.lay_logout:
                mAuth.signOut();
                intent = new Intent(this, MainActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                break;
        }
        if (intent != null) {
            startActivity(intent);
        }
        drawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }

As you can see I commented the intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); as part of debugging the issue. I want the navigation process not to start a new screen, rather move to it.

Also the OnCreate method in the MenuActivity looks like this:


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

    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
    }

    drawerLayout = findViewById(R.id.drawer_layout);
    navigationView = findViewById(R.id.lay_nav_view);

    toggle = new ActionBarDrawerToggle(this, drawerLayout,
            R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawerLayout.addDrawerListener(toggle);
    toggle.syncState();
    navigationView.setNavigationItemSelectedListener(this);

    mAuth = FirebaseAuth.getInstance();
    logged_user = mAuth.getCurrentUser();

    if (logged_user != null) {
        // Get data from firebase in order to set the avatar
        // and user name in the menu
    }
}

protected void setLayoutView(int layout) {
    LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (inflater != null) {
        View contentView = inflater.inflate(layout, null, false);
        drawerLayout.addView(contentView, 0);
    }
}

Each one of the activitise extends the MenuActivity and does the following in their onCreate method:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setLayoutView(R.layout.activity_about); // My method which loads UI
        // other code
    }

So, as you can see, each one of the activities is extending the MenuActivity . As I understand, this means that everytime I navigate from one activity to another, the OnCreate of MenuActivity is being executed again. I fetch data from the Firebase in that method in order to set the username and the avatar in the top of the menu. So everytime I navigate from one activity to another, it will fetch again and again. How can I make the menu to load only once in a logged mode? Also, thanks to all of you that have read this topic (I know it's long).

EDIT : To make it more clear, I'm adding the hierarchy of my code:

在此处输入图像描述

Maybe the solution for this issue is to make the MenuActivity a singleton class?

All I want to have a menu on each one of the activities and fetching the data only once.

Hello you could use NavigationDrawer with fragments. That will be the most optimal solution and easy, You could also use Navigation Component from Jetpack to change the destinations.

you could use something like this,the following layout uses a DrawerLayout with two child views: a NavHostFragment to contain the main content and a NavigationView for the contents of the navigation drawer.

<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<androidx.drawerlayout.widget.DrawerLayout       xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
<fragment
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:id="@+id/nav_host_fragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:navGraph="@navigation/nav_graph" />

<!-- Container for contents of drawer - use NavigationView to make configuration easier -->
<com.google.android.material.navigation.NavigationView
    android:id="@+id/nav_view"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:fitsSystemWindows="true" />

Next, connect the DrawerLayout to your navigation graph by passing it to AppBarConfiguration, as shown in the following example:

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

Next, in your main activity class, call setupWithNavController() from your main activity's onCreate() method, as shown below:

override fun onCreate(savedInstanceState: Bundle?) {
setContentView(R.layout.activity_main)

...

val navController = findNavController(R.id.nav_host_fragment)
findViewById<NavigationView>(R.id.nav_view)
    .setupWithNavController(navController)

}

Thats it, then you can use the navContoller to navigate to any fragment, and rest of what you need is a navigation graph and actions set on destinations to navigate between fragments this way:

navController.navigate(R.id.actionSettingFragment_to_ContactsFrament)

Hope this is kinda helpful. I have a blog written on this so please check it if it is useful to you.

There's more than one way to resolve your issue. I'm going to provide different approaches towards a solution.

Repository

To reuse the data you fetch from Firebase , it needs to be persisted or cached within your application. In general you'd implement an repository abstraction around the Firebase . This repository could be a singleton and just cache the data in memory directly. You only have to make sure to cleanup the cache when necessary. The MenuActivity mustn't be a singlton .

Intent extras

Instead of storing the data in memory, you could provide it as Intent extras . Whenever the data is present, just skip the loading and reuse the data provided.

Fragments

Instead of a stack of activities, you could use fragments . So you'll have a single activity and just replace the fragments within it. With this approach you'll just define a single drawer layout you'll automatically use with every fragment. This approach enables you to use Navigation components as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM