简体   繁体   中英

Extract function which is starting new Activity and is used in many different activities

I've started to learn Xamarin few days ago and now I'm facing a refactoring problem.

Currently I've got multiple screen layout with bottom navigation bar for TABs to switch between screens. Every activity's layout is adding BottomNavigationBarView at the bottom and every activity's .cs initialize NavigationItemSelected inside their OnCreate methods in this way:

var bottomNavigationBar = FindViewById<BottomNavigationView>(Resource.Id.bottomNavigationBar);

bottomNavigationBar.SelectedItemId = Resource.Id.navigationBarMain; //This id is different for every activity
bottomNavigationBar.NavigationItemSelected += (sender, e) =>
{
    switch (e.Item.ItemId)
    {
        case Resource.Id.navigationBarMain:
            StartActivity(typeof(MainActivity));
            break;
        case Resource.Id.navigationBarHistory:
            StartActivity(typeof(HistoryActivity));
            break;
        case Resource.Id.navigationBarSettings:
            StartActivity(typeof(SettingsActivity));
            break;
    }
};

I would like to extract this piece of code into external function and just call it from every activity only with Resource.Id... parameter.

How can I do that?

You could create a "BaseActivity" which inherits from the Android activity class, and all your activities inherit from. Then you could put a method in the base activity to do what you want. If you set your Activities to inherit from this activity you will be able to easily call it.

Your base activity would look something like this:

 [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar")]
    public class BaseActivity : AppCompatActivity
    {

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            
    }

protected virtual void SetBottomNavigationBar(int id)
    {
        var bottomNavigationBar = FindViewById<BottomNavigationView>(id);

        bottomNavigationBar.SelectedItemId = Resource.Id.navigationBarMain; //This id is different for every activity
        bottomNavigationBar.NavigationItemSelected += (sender, e) =>
        {
            switch (e.Item.ItemId)
            {
                case Resource.Id.navigationBarMain:
                    StartActivity(typeof(MainActivity));
                    break;
                case Resource.Id.navigationBarHistory:
                    StartActivity(typeof(HistoryActivity));
                    break;
                case Resource.Id.navigationBarSettings:
                    StartActivity(typeof(SettingsActivity));
                    break;
            }
        };
    }
}

Then in your other activities you would do something like this:

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
    public class MainActivity :BaseActivity 
    {

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            //other code

            SetBottomNavigationBar(Resource.Id.bottomNavigationBar);
        }

}

Instead of the inheritance that David Christopher Reynolds suggests here. I would instead consider using composition instead. This way you don't accidentally end up creating this "God"-object of a base class that you start inheriting from everywhere.

Instead, make a strategy:

public interface INavigationStrategy
{
    void Navigate(int selectedItem);
}

public class BottomBarNavigationStrategy : INavigationStrategy
{
    private Context _context;

    public BottomBarNavigationStrategy(Context context)
    {
        _context = context;
    }

    public void Navigate(int selectedItem)
    {
        switch(selectedItem)
        {
            case Resource.Id.navigationBarMain:
                _context.StartActivity(typeof(MainActivity));
                break;
            case Resource.Id.navigationBarHistory:
                _context.StartActivity(typeof(HistoryActivity));
                break;
            case Resource.Id.navigationBarSettings:
                _context.StartActivity(typeof(SettingsActivity));
                break;
        }
    }
}

Then you can use it in your code like:

var navigationStrategy = new BottomBarNavicationStrategy(this);
bottomNavigationBar.NavigationItemSelected += OnItemSelected;

void OnItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
    navigationStrategy.Navigate(this, e.Item.ItemId);
}

This way you can easily share code across classes, without inheritance and limiting yourself to using a Base class for everything.

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