cool hit counter I don't write a single line of code to implement the Toolbar!_Intefrankly

I don't write a single line of code to implement the Toolbar!


Original article address: http://www.jianshu.com/p/75a5c24174b2 qqgroup: 301733278

preamble

length previous article It's been more than two months since I published my article, and I haven't written it in those two months but I've been updating my MVPArms framework ,let He gradually moved towards Configurable Integration Framework development

Just a while ago I was in Hongyang Public I saw an article on the website, probably about how to package BaseActivity ,let Activity This can be achieved with a few lines of code ToolBar

It just so happens that I of MVPArms The framework has also been updated with a feature :

By not inheriting from the Activity Fragment to implement some of the public logic that previously needed to be wrapped into the BaseActivity BaseFragment through inheritance, as well as listening to the entire App all Activity and Fragment (including tripartite libraries) and can insert code into its life cycle

Then I'll tell you how I got Activty to implement Toolbar without using inheritance and without writing a single line of code.

Why I advocate less encapsulation of BaseActvity and less inheritance

BaseActivity Encapsulated more, Apart from being badly managed, And most importantly. of just a little be, Java Only single inheritance, When if you of Activity Need to use to a certain tripartite repository, that one tripartite repository You must be allowed to inherit from it of Activity however be You need to encapsulate yourself again. of BaseActivity What do you do when there's something about it? You can't change the three-way library. Activity So you only have to change your BaseActivity Let it go to inherit the three-way library of Activity, however be When the change was made BaseActivity After, it was found that there was a lot of inheritance from BaseActivity of Activity There's no need for this. tripartite repository, But forced to inherit it of Activity , at which point you have to repackage another BaseActivity

When this happens of more, you of BaseActiviy It's a vicious circle, so I'm not just advocating. App Less encapsulation for developers BaseActivity Less use of inheritance, also promoted tripartite repository Less encapsulation for developers BaseActivity Less inheritance, why? Because when App developers of Activity Requires the use of two tripartite repository, both tripartite repository All need to inherit it of Activity, at this time You let App What about the developers? So as a Configurable Integration Framework Author, I can't let the developers go and just change my BaseActivity I'll have to go through the other extensions to fix this

Get to the point.

okay Get to the point., To solve the above refer to of issues, We need to think about why we must encapsulate BaseActivity By inheriting to implement some Activity of public logic, rather than being able will Public logic encapsulated in other classes?

The answer is simple, because we have to use the Activity of Some life cycle,(located) at corresponds of in the life cycle execute corresponds of logic (loanword) This... just (emphasis) be We can't encapsulate other classes by realize of reason, find The key to the problem., Then we'll start with the life cycle to solve the problem

ActivityLifecycleCallbacks

refer to Activity life cycle, at this point I'm going to introduce an interface that is called ActivityLifecycleCallbacks I don't know if any of the students have known about it before? It doesn't matter if you don't know, I'll introduce it now.

ActivityLifecycleCallbacks be Application in statement of An internal interface, Let's take a look at it. of structure

public interface ActivityLifecycleCallbacks {
        void onActivityCreated(Activity activity, Bundle savedInstanceState);
        void onActivityStarted(Activity activity);
        void onActivityResumed(Activity activity);
        void onActivityPaused(Activity activity);
        void onActivityStopped(Activity activity);
        void onActivitySaveInstanceState(Activity activity, Bundle outState);
        void onActivityDestroyed(Activity activity);
    }

What's the purpose of this interface?

Application Provide that there is a registerActivityLifecycleCallbacks() of approach, Need to pass in of The parameters on be this one ActivityLifecycleCallbacks interface, role harmony you bet. of sure!, just (emphasis) be(located) at You call this method to pass in this interface realize post-class, The system will(located) at everyone Activity The corresponding method in this implementation class is called after the execution of the corresponding life cycle, remember that each!

This is when we come up with a requirement to implement, to close all Activity ! You're still going through inheritance BaseActivity (located) at BaseActivity of onCreate in which this will be Activity Join the collection????

Well, I'll tell you the downside of that now, if you App in Open with other tripartite repository of Activity This three-way library is certainly not inherited from you. BaseActivity , at this time What do you do?? what's be done?

at this time ActivityLifecycleCallbacks It'll come in handy, App in of all Activity As soon as the lifecycle is executed, the corresponding method of the interface implementation class must be called, so you can add the onActivityCreated in will all Activity Add to the collection, so that whether you're a triple library or not Activity I can traverse the set. finish all of Activity

Implementing ToolBar with ActivityLifecycleCallbacks

Setting the NoActionBar theme

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
</application>

establish ToolBar of Layout and citation

Let's not get hung up on my Toolbar The layout, here is just the implementation of the idea, you can change the layout to your own way

<me.jessyan.art.widget.autolayout.AutoToolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="120px"
    android:background="?attr/colorPrimary"
    app:contentInsetStart="0dp"
    >

    // toolbar  in of return to buttons
    <com.zhy.autolayout.AutoRelativeLayout
        android:id="@+id/toolbar_back"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="left"
        >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="30px"
            android:layout_marginRight="30px"
            android:layout_centerVertical="true"
            android:src="@mipmap/login_return"/>

    </com.zhy.autolayout.AutoRelativeLayout>

    // toolbar  in of title name
    <TextView
        android:id="@+id/toolbar_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18dp"
        android:textColor="#fff"
        android:layout_gravity="center"
        tools:text="MVPArt"/>


</me.jessyan.art.widget.autolayout.AutoToolbar>

In case you need to Toolbar of Activity disposition in include on top of of disposition

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    // will Toolbar  Wrap it in.
    <include layout="@layout/include_title"/>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingLeft="15px"
        android:paddingTop="15px"
        >

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical"
            tools:listitem="@layout/recycle_list"
            />

    </android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>

Implement ActivityLifecycleCallbacks and register them with the Application

hereunder only be right ToolBar easy of set up, You can configure your own more complex of functionalities, How imaginative are you?, Here's how powerful it is.

public class WEApplication extends BaseApplication{

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                 // This is where you set the toolbar and title globally for the Activity, you can imagine how powerful this is, and the operations that were previously put into the BaseActivity can be put here
                if (activity.findViewById(R.id.toolbar) != null) { // find Toolbar  And replace Actionbar
                    if (activity instanceof AppCompatActivity) {
                        ((AppCompatActivity) activity).setSupportActionBar((Toolbar) activity.findViewById(R.id.toolbar));
                        ((AppCompatActivity) activity).getSupportActionBar().setDisplayShowTitleEnabled(false);
                    } else {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            activity.setActionBar((android.widget.Toolbar) activity.findViewById(R.id.toolbar));
                            activity.getActionBar().setDisplayShowTitleEnabled(false);
                        }
                    }
                }
                if (activity.findViewById(R.id.toolbar_title) != null) { // find Toolbar  of The title bar and set up title name
                    ((TextView) activity.findViewById(R.id.toolbar_title)).setText(activity.getTitle());
                }
                if (activity.findViewById(R.id.toolbar_back) != null) { // find Toolbar  of return to buttons, furthermore set up Click event, Click to close this Activity
                    activity.findViewById(R.id.toolbar_back).setOnClickListener(v -> {
                        activity.onBackPressed();
                    });
                }
            }

            ...
            
        });
    }
}

(located) at AndroidManifest.xml in set up Label

In the future you want to make a Activity realize ToolBar There are only two things to do:

1.(located) at layout file in

 <include layout="@layout/include_title"/>

2.(located) at AndroidManifest.xml Give this. Activity set up Label This... Label just (emphasis) be title name

        <activity
            android:name=".mvp.ui.activity.SplashActivity"
            android:label="@string/app_name"
            />

Introducing one more global configuration for all Activity How to enter the exit transition animation, settings Theme properties

 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowAnimationStyle">@style/AnimaActivity</item>
    </style>
    <style name="AnimaActivity">
        <item name="android:activityOpenEnterAnimation">@anim/translate_right_to_center</item>
        <item name="android:activityOpenExitAnimation">@anim/translate_center_to_left</item>
        <item name="android:activityCloseEnterAnimation">@anim/translate_left_to_center</item>
        <item name="android:activityCloseExitAnimation">@anim/translate_center_to_right</item>
    </style>

(located) at Activity in You don't have to inherit any at all. Activity You can implement a lot of complicated functions without writing a single line of code.

A lot of public logic can be written to ActivityLifecycleCallbacks in, You just have to try. Your imagination is as strong as this place.

extensions

Because all Activity During the execution of the corresponding life cycle , ActivityLifecycleCallbacks corresponds of methods are called, some Activity It may not be necessary Toolbar , such as the three-way library of Activity , although in onActivityCreated approach in, Judgmental. ToolBar of Id If you can't find it, don't execute the setting ToolBar of logic (loanword), however be It's not elegant enough.

Custom Interface

In fact, we can make Activity realize corresponds of Custom Interface, (located) at onActivityCreated in instanceof If you do not implement this custom interface, it means that you do not need to set ToolBar That's a lot more elegant.

Stored data

(located) at ActivityLifecycleCallbacks in, all Activity execute corresponds of post-life cycle, It corresponds to of methods are called So... We must distinguish between this Activity the end be who Activity So... ActivityLifecycleCallbacks Each method will pass in Activity As a parameter, we can use it to distinguish Activity

public void onActivityCreated(Activity activity, Bundle savedInstanceState){
    if (activity instanceof xxxActivity){
        ....
    }

}

however be Another problem has arisen with this ActivityLifecycleCallbacks be for public use of, When a Activity (located) at onCreate method produces an object ,we need to add a new object to this Activity execute onDestroy What should I do if I need this object? Because each Activity We can't store this object in the ActivityLifecycleCallbacks Yes.

You can use it now. Activity.getIntent to store some data, Intent Holding one of the Bundle Objects can store some data,

Give me an example.

We need to use ActivityLifecycleCallbacks Achieved for all Activity execute ButterKnife.bind(activity)

Bundle in Can store Parcelable targets

public class ActivityBean extends Parcelable {
    private Unbinder unbinder;
    public void setUnbinder(Unbinder unbinder){
        thid.unbinder = unbinder;
    }
    
    public Unbinder getUnbinder(){
        return unbinder;
    }
}

(located) at ActivityLifecycleCallbacks Execute the corresponding logic

public class WEApplication extends BaseApplication{

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                ActivityBean bean = new ActivityBean();
                Unbinder unbinder = ButterKnife.bind(activity);
                bean.setUnbinder(unbinder);
                activity.getIntent().putExtra("ActivityBean", bean);
           }

            ...
            
            @Override
            public void onActivityDestroyed(Activity activity) {
                ActivityBean bean = activity.getIntent().getParcelableExtra("ActivityBean");
                bean.getUnbinder().unbind();
            }
        }
            
        });
    }
}

Requires the Activity to initialize something, or provide some data

BaseActivity There are times when it's necessary, son. Activity Implement certain methods or provide certain data, such as the need for sub Activity realize initView return to setContentView() in of disposition ID ,achieve initData initialize some data, so that it is not necessary to Activity Rewrite again onCreate , for regulatory purposes, so that the use of ActivityLifecycleCallbacks I can do the same, so what do I do?

simply require Activity Implement a custom interface

public interface IActivity {

    int initView();

    void initData();

}

Then in ActivityLifecycleCallbacks of onActivityCreated in Calling these methods, then you can realize

public class WEApplication extends BaseApplication{

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            if (activity instanceof IActivity) {
               activity.setContentView(((IActivity)activity).initView());
               ((IActivity)activity).initData();          
            }
              
           }

            ...
       
        }
            
        });
    }
}

caveat emptor

thanks to ActivityLifecycleCallbacks in all approach of The timing of the calls are be(located) at Activity Corresponding life cycle of Super method, so it's done in the Activity of onCreate approach in use setContentView It is necessary to have an in super.onCreate(savedInstanceState); Before, or before onActivityCreated approach in findViewById Will find no way to find

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

You can also use a custom interface in conjunction with the above, calling initView After, in findViewById() find ToolBar

accidentally realize So much had to be written before to BaseActivity in It is only through inheritance that you can reach of functionalities, Found none. BaseActivity , There's nothing uncomfortable about it. of area, Suddenly I feel so good. ?, Follow me now!, Although I don't update the blog very often, however be I update of essay(located) at Absolute guarantee on quality!

conclude

it's worth noting that... ActivityLifecycleCallbacks You can register more than one, and you can add various ActivityLifecycleCallbacks Combine as needed to meet different needs, and Okhttp of Interceptor resemble

Now the whole App of all Activity harmony Fragment Any lifecycle call will be intercepted, Apply to my frame and it will be dynamic of toward all Activity harmony Fragment of Insert any code for the corresponding life cycle, for example LeakCanary of RefWatcher.watch(fragment) It can also be inserted directly into the three-way library of Fragment in, And you don't have to change the base class if there are any changes to the code, somewhatAop of meaning

above refer to of thought and The solution has been used to me of MVPArms framework in, Want to know more details of For usage, check out my offramework realize, Above me. refer to of all of realize, in fact all be easiest of Some needs, I believe it has turned the previous of realize way, And more elegant( Since I'm proposing this feature from the perspective of a three-way library designer, I must leave the only chance of inheritance to other Activities, so if you don't find it elegant compared to the previous approach, forget it! ), let alone worry about Java Binding of single inheritance

But don't think, ActivityLifecycleCallbacks can only realize These are simple. of need, It can also be used for more and more complex of Above the Function, also be Before I of talk, You just have to try. Your imagination is as strong as this place. , thought and The solution has been introduced of It's clear, As for more demand of realize It's up to everyone to try, Although I'm not sure about the previous encapsulation BaseActivity All functions implemented through inheritance can be ActivityLifecycleCallbacks But I think most of the functions are still possible.

Everyone used to be be Share your own package of BaseActivity , Maybe one day people will start sharing their own writing of ActivityLifecycleCallbacks this! When before of way has not satisfied us of need, Dare to jump out of tradition of manner, Try differently of solution, to widen yourself of visual field, grow yourself of technology, MVPArms It's a constant work in progress!


Here's another thing to say, everyone of The idea is different, Consider the problem of The angle is different, You agree with me, I don't agree with me, it doesn't affect my exploration of the unknown of footsteps, At least me be(located) at Use me of Innovative ideas, Solve some things I think are necessary of issues, harmony Previous of Article like, I'll just be Prefer to use a different of Ideas to solve the same of issues, No matter what you be No, I don't think so., I at least use this you don't think it's feasible of Ideas realize I want to reach it of effect, A benevolent man sees a benevolent wise man sees a wise man, If our minds don't collide, Then please cherish me of The fruits of labor

I'll say one more thing about some of the comments, registerActivityLifecycleCallbacks() interior be handful ActivityLifecycleCallbacks Add to a collection in So... ActivityLifecycleCallbacks You can add more than one, furthermore ActivityLifecycleCallbacks only be(located) at Project initialization of time is loaded into the collection in, Nothing is initialized, harmony Add a listener for a reason, use of be Observer mode So... Don't say Application What happens when there's so much code?, Okhttp of Interceptor of More code, too be(located) at Okhttp Do you think it will have any effect if it is added during initialization?


Hello My name is Jessyan, if you like my articles, you can follow me on the following platforms

-- The end


Recommended>>
1、Will blockchain projects explode in 2018
2、AI Healthcare Tencent has teamed up with an American academic bully to do something big
3、Why artificial intelligence cant replace doctors yet Here are 5 reasons why
4、Lu Xinning deputy editorinchief of Peoples Daily We must think about these four questions about the era of smart media
5、Robots are already selfaware will artificial intelligence destroy the world

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号