The introduction

What about Christmas? I do not Christmas, by the ticket circle bask in the happiness of sadomasochistic, or at home to sum up their own bar. I said I would encapsulate a set of libraries belonging to their own, and strive to send out before the New Year’s day, as a New Year’s gift to myself, to everyone. Well, today we are going to talk about how we can encapsulate our BaseActivity and BaseFragment in our projects and by referring to our code.

How to encapsulate?

When it comes to encapsulation, we first think of object-oriented. The understanding of object-oriented in my mind is encapsulation, inheritance and polymorphism. After I really enter the development work, I gradually have a deeper understanding of it. In fact, the deepest time is in the process of communicating with friends, he gave me a lot of inspiration, so technical communication is actually very important. So what is encapsulation? That has to mention the object oriented, the following talk about my own understanding, not necessarily right, so please forgive me:

First: What is the fundamental nature of object orientation? A simple sentence, in fact, is the property and method bind together. Here’s the simplest example: When we write an activity, we can understand the attribute macro parameters for various components as well as some that we use, and then put our processing business logic code written in their own way, almost all classes are so properties – methods together, seal also hide the internal implementation mechanism of a class, Thus, the internal structure of the class can be changed without affecting the user, while protecting the data.

Then: the concept of encapsulation comes out, when we feel that an activity is too bloated, code is too redundant, we will consider encapsulation, a complex business logic package into a tool class, separate out for other use, another example: download files… You can probably wrap a utility class for downloading files. I won’t introduce you too much.

When our class does not meet our specific needs, we also have inheritance. In popular terms, inheritance means that the son inherits the genes of the father and also derives new genes. Inheritance is the derivation of a new class from an existing class, which can absorb the data attributes and behavior of the existing class and extend the new capabilities. (You can see this from my BaseEventActivity and BaseParentActivity below)

Inheritance, of course, is intended to reuse superclass code and prepare for polymorphism. I’ve always felt that polymorphism was created to separate interfaces from implementation, improve code organization, and make code more readable. In some very simple cases, we might be able to develop programs that meet our needs without polymorphism, but most of the time, without polymorphism, the code would be extremely difficult to maintain. It also makes up for the lack of single inheritance in Java. And of course there’s also abstraction, which is taking something out of the real world and expressing it in program code, and abstracting it out is usually called a class or an interface.

Ok, this object oriented I may understand or relatively shallow, there are wrong places, do not spray ah, many correct. This principle leads to the following BaseActivities and BaseFragments.

BaseActivity encapsulation

  • BaseEventActivity Base class for the event bus
  • The BaseParentActivity annotation binds to the base class
  • BaseStatusBarActivity The notification bar is immersed in the base class

1. BaseEventActivity

In my previous projects, I used EventBus to subscribe/publish events instead of intents, handlers, and BroadCast to transmit messages between fragments, activities, services, and threads. However, we found that each activity has to register and unregister events. Register eventbus.getDefault ().register(this) in OnCreate(); Unregister OnDestroy() : eventbus.getDefault ().unregister(this); It was a bit cumbersome, so we wrapped BaseEventActivity as the root Activity and put all the events in BaseEventMap. The problem we need to discuss is that this results in all activities subscribing to the Event bus. After a POST is published, All activities will be monitored and then judged by the Event type. I wonder if there is anything inappropriate in this case.

Take a look at BaseEventMap:

All events inherit from BaseEvent, which has two parameters:

public static class BaseEvent{
        public String code;        / / error code

        public String message;     // Error message
    }Copy the code

There are also abnormal error events. We can use some error information methods to obtain error information through error codes for prompting. Of course, the type can be defined by ourselves.

package com.hankkin.hlibrary.event;

import android.text.TextUtils;
import java.util.HashMap;

/** * Created by Hankkin on 16/12/23. * note: Time bus class */

public class EventMap {

    // Event bus base class
    public static class BaseEvent{
        public String code;        / / error code

        public String message;     // Error message
    }

    // Error class memory
    public static HashMap<String.String> ERROR_MAPS = new HashMap<>();
    // Store various error messages locally
    static {
        ERROR_MAPS.put("1"."Upload failed");
        ERROR_MAPS.put("0"."Connection timed out. Please check the network and try again.");
        ERROR_MAPS.put("1"."Server internal error, please try again.");
        ERROR_MAPS.put("119"."Client does not have permission to perform this operation");
        ERROR_MAPS.put("127"."Phone number is invalid, captcha has not been sent.");
        ERROR_MAPS.put("206"."Operation failed");
        ERROR_MAPS.put("210"."The password is incorrect. Please re-enter it.");
        ERROR_MAPS.put("211"."User does not exist, please re-enter");
        ERROR_MAPS.put("213"."The phone number has not been registered.");
        ERROR_MAPS.put("214"."This mobile phone number has been registered, please change it and register again.");
        ERROR_MAPS.put("215"."The phone number has not been verified and the password cannot be changed.");
        ERROR_MAPS.put("601"."Sending SMS verification code too fast, please try again later.");
    }

    /** * returns an error message based on the error code * @param code Error code * @return */
    public static String pickMessage(String code){
        if (TextUtils.isEmpty(code)){
            return null;
        }
        if (ERROR_MAPS.containsKey(code))
            return ERROR_MAPS.get(code);
        return null;
    }

    /** * error exception event */
    public static class HExceptionEvent extends BaseEvent{
        public boolean isPickedMessage = false;

        public HExceptionEvent(String message){
            this.message = message;
            this.isPickedMessage = true;
        }

        public HExceptionEvent(int code,String message){
            this.code = String.valueOf(code);
            this.isPickedMessage = ERROR_MAPS.containsKey(this.code);
            String pick = pickMessage(this.code);
            this.message = TextUtils.isEmpty(pick) ? message : pick; }}/ * * -- -- -- -- -- -- -- -- -- -- - beautiful line, you can define your event in the inheritance BaseEvent -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
}Copy the code

Then we define the time observer in the BaseEventActivity, and uniformly handle the exception Event for Toast prompt:

 /** * event observer * @param event */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(EventMap.BaseEvent event){
        if(event ! =null && event instanceof EventMap.HExceptionEvent){
            if(! TextUtils.isEmpty(event.message)){ ToastUtils.showToast(mActivity,event.message); }}}Copy the code

2. BaseParentActivity

In the same way, we did the following in BaseParentActivity:

  • Uniformly annotating binding initBind()
  • Layout loads setContentView(getContentId());
  • Unified Titlebar initializes initToolBar()
  • InitViews ()
  • The Activity jump gotoActivity

Layout loading initBind() and component initializing initViews() are methods that every activity writes to, so we implement BaseViewInterface, which has two methods:

package com.hankkin.hlibrary.base;

/** * * @author Hankkin * */
public interface BaseViewInterface {

    public int getLayoutId();

    public void initView();

}Copy the code

Override these two methods for all activities, and look at the code (there are also activity jumps, photo albums, and other methods) :

package com.hankkin.hlibrary.base;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import butterknife.ButterKnife;
import com.hankkin.hlibrary.AppManager;
import com.hankkin.hlibrary.R;
import java.io.File;

/** * Created by Hankkin on 16/8/7. */
public abstract class BaseParentActivity extends BaseEventActivity implements BaseViewInterface {

    public static final int REQUEST_CAMERA = 100;
    public static final int REQUEST_GALLERY = 101;
    public static final int PHOTO_REQUEST_CUT = 102;

    protected LayoutInflater mInflater;
    protected String TAG;
    protected Activity activity;

    public interface OnRightClickListener {
        void rightClick();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        TAG = this.getClass().getSimpleName();
        AppManager.getAppManager().addActivity(this);
        if(getContentId() ! =0) {
            setContentView(getContentId());
        }
        super.onCreate(savedInstanceState);
        mInflater = getLayoutInflater();
        activity = this;
        initBind();
        initView(savedInstanceState);
    }

    /** * Starting an Activity does not close the current Activity */ by default
    public voidgotoActivity(Class<? > clz) { gotoActivity(clz,false.null);
    }

    public voidgotoActivity(Class<? > clz, boolean isCloseCurrentActivity) { gotoActivity(clz, isCloseCurrentActivity,null);
    }

    public voidgotoActivity(Class<? > clz, boolean isCloseCurrentActivity, Bundle ex) { Intent intent =new Intent(this, clz);
        if(ex ! =null) intent.putExtras(ex);
        startActivity(intent);
        if(isCloseCurrentActivity) { finish(); }}/** * uniformly initializes titlebar */
    protected Toolbar initToolBar(String title) {
        ImageView ivBack = (ImageView) findViewById(R.id.tool_bar_back);
        TextView tvTitle = (TextView) findViewById(R.id.tv_toolbar_title);
        tvTitle.setText(title);
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
        toolbar.setContentInsetsRelative(10.0);
        ivBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public voidonClick(View v) { back(); }});return toolbar;
    }

    /** * Initialize titlebar */
    protected Toolbar initToolBarRightImg(String title, int rightId, final OnRightClickListener listener) {
        ImageView ivBack = (ImageView) findViewById(R.id.tool_bar_back);
        TextView tvTitle = (TextView) findViewById(R.id.tv_toolbar_title);
        tvTitle.setText(title);
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
        toolbar.setContentInsetsRelative(10.0);
        ivBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public voidonClick(View v) { back(); }}); ImageView ivRight = (ImageView) findViewById(R.id.iv_tool_bar_right); ivRight.setImageResource(rightId); ivRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public voidonClick(View v) { listener.rightClick(); }});return toolbar;
    }


    /** * Uniformly initializes the text */ to the right of titlebar
    protected Toolbar initToolBarRightTxt(String title, String right, final OnRightClickListener listener) {
        ImageView ivBack = (ImageView) findViewById(R.id.tool_bar_back);
        TextView tvTitle = (TextView) findViewById(R.id.tv_toolbar_title);
        tvTitle.setText(title);
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
        toolbar.setContentInsetsRelative(10.0);
        ivBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public voidonClick(View v) { back(); }}); TextView tvRight = (TextView) findViewById(R.id.tv_tool_bar_right); tvRight.setText(right); tvRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public voidonClick(View v) { listener.rightClick(); }});return toolbar;
    }

    protected void back() {
        if(activity ! =null) {
            activity.finish();
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    protected int getContentId() {
        return getLayoutId();
    }

    protected voidinitBind() { ButterKnife.bind(activity); }}Copy the code

3. BaseStatusActivity

With the improvement of Android system version, most apps have adapted the immersion status bar. Otherwise, the black status bar is too awkward. There are also many articles on the immersion notification bar, but I think the best one is sun Wukong’s one, which is well encapsulated and basically adapted to all situations. Even the pictures in the Fragment and transparent notification bar have been adapted, and I have them in my library. There is no more to say in this, it is not perfect:

package com.hankkin.hlibrary.base;

import android.app.Activity;
import android.os.Bundle;
import butterknife.ButterKnife;
import com.hankkin.hlibrary.R;
import com.hankkin.hlibrary.utils.statusbar.StatusBarUtil;

/** * Created by Hankkin on 16/12/23. * note: Set status bar base class */

public abstract class BaseStatusActivity extends BaseParentActivity{
    protected String TAG;
    protected Activity activity;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        TAG = this.getClass().getSimpleName();
        activity = this;
        super.onCreate(savedInstanceState);
        setStatusBar();
    }

    private void setStatusBar() {
        StatusBarUtil.setColor(this, getResources().getColor(R.color.colorPrimary), 0); }}Copy the code

Eventbus2 is a reflection Class, and EventBus3 is an annotation apt, so I don’t think subclasses should be added. There is no problem with current use. Well, BaseFragment loading is something I’ll cover in my next article, and thank you for your article:

StatusBarUtil Status bar tool class (immersive/color-changing status bar)

Li Ge’s article