Android Development Specification

Refer to the article

The main points learned from the study of Android development specifications are as follows: 1. The benefits of package name division using PBF for subcontracting, because the same function code is in the same package, it is easy to delete functions and reduce package coupling; 2. Having a private scope means that one function cannot access anything from another function; The size of the package indicates a problem with the function. If the package is too large, the function needs to be refactured. 2, the main thing to remember is that static fields start with S and non-static fields start with M. Other conventions are familiar. 3. The code style specification mainly learns the passing of Activities and Fragments. Directly use Live Templates written by AndroidStudio and input starter or newInstance to generate initiators. You can use Ext to define global variables in your build.gradle file

MVP

An architecture project officially produced by Google, which is an evolutionary version of MVC, in which an Activity functions both like a View and like a Controller. After the evolution, a Presenter appears, which completely treats an Activity as a View layer. Presenter is responsible for the interaction between the View and Model layer. The Controller in MVC doesn’t completely disconnect the Model from the View. The Model and View can interact with each other. The MVP decoupled the two completely. MVP simplifies the Activity code by extracting the business logic related code into the Presenter layer for processing. MVP also added a lot of classes, but made the code very clear.

Componentized development

Componentized architecture consists of three layers. The basic layer mainly encapsulates some common operations, and different components can be referenced. The component layer contains functional components, each of which is a Module; The application layer refers to different components to achieve the final business function. Componentized development needs to solve the following problems: 1. Each component is a whole, and the development process needs to meet the requirements of independent running and debugging of components. The solution: Add a Boolean variable to the gradle.properties configuration file in the component Module. Use this Boolean value in build.gradle to determine whether you want to debug separately or integrate. Then modify the value of the Apply Plugin, whether the applicationId needs to be configured, and the adjustments to the Manifest file used. 2, components between the mutual call and data transfer, interface jump to create ComponentBase module, for the base layer depends on, in which the definition of components to provide external access to the Service interface and empty implementation of the class, and then in the component specific implementation, Add the objects of the classes that implement these methods to ServiceFactory provided by ComponentBase, and other components can call ServiceFactory to get the methods and data they want to call. The ARouter of the third party is used to realize the routing function between components. After it is initialized in the Application, interface hops can be realized through the configured routing. 3. One way for a main project to access a Fragment in a component is to initialize the Fragment directly through reflection and pass it to an Activity. The alternative is the same as ServiceFactory. Add a method to get a Fragment in the Service interface and return a Fragment object in the component’s implementation class so that the Fragment can be retrieved through ServiceFactory. 4, integrated debugging, if rely on a number of components, how to rely on part of the compiler through this problem through the above problem has been solved, there is no direct correlation between components, are through the Service interface to achieve ComponentBase, because the default to provide empty implementation, So even if the invoked component is not initialized, the call does not raise an exception, just an empty implementation is invoked.

Dagger2

Dagger2 is a dependency injection framework, which uses apt plug-in to generate corresponding injection code at compile time. The purpose of dependency injection is to reduce the program coupling, coupling is because of the dependency between classes, through dependency injection to solve the problem of dependency between classes. I won’t go into details about how to introduce Dagger2, but I’ll start with a simple piece of code that implements dependency injection in MVP. Although it may seem more complicated than direct instantiation, this approach solves the coupling problem of the program by adding some helper classes, removing direct dependencies between classes.

public class MainActivity extends AppCompatActivity implements MainContract.View {
    @Inject
    MainPresenter mainPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         / / initialization
         DaggerMainComponent.builder()
                .mainModule(new MainModule(this))
                .build()
                .inject(this);
        Call the Presenter method to load datamainPresenter.loadData(); }}public class MainPresenter {
    private MainContract.View mView;
    
    @Inject
    MainPresenter(MainContract.View view) {
        mView = view;
    }    
    public void loadData(a) {
        // Call the Model layer method to load the data
    }

@Module
public class MainModule {
    private final MainContract.View mView;

    public MainModule(MainContract.View view) {
        mView = view;
    }

    @Provides
    MainView provideMainView(a) {
        returnmView; }}@Component(modules = MainModule.class)
public interface MainComponent {
    void inject(MainActivity activity);
}

public interface MainContract {
    interface View extends IView {}interface Presenter extends IPresenter {
        void loadData(a);
    }

    interface Model extends IModel {}}Copy the code

Then we rebuild the project and inject it with the generated DaggerMainComponent. Add the following code to the MainActivity:

DaggerMainComponent.builder()
               .mainModule(new MainModule(this))
               .build()
               .inject(this);
Copy the code

Why MainActivity instantiates mainPresenter with @Inject annotation and how they are generated? First, a few notes:

  • Inject property or constructor with this annotation will participate in dependency injection, and Dagger2 instantiates the class with this annotation
  • @Module is a class with this annotation that Provides dependencies. It defines methods that start with the provide annotation with the @provides annotation. These methods are the provided dependencies.
  • @Component is the bridge between @Inject and @Module, taking dependencies from @Module and injecting them into @Inject

It is easy to understand the relationship between MainActivity and MainPresenter. First, MainActivity wants to rely on MainPresenter. Then, it finds that the Constructor of MainPresenter has the @inject annotation, which can be instantiated. But there is a parameter called MainContract.View, so we need to provide the dependency via provideMainView in the MainModule, which is passed in as the constructor argument to the MainModule. For a deeper understanding, you can see the source code of the reference article provided above, the explanation is very clear, through the relationship between the generated classes, to achieve the injection process. The core part is DaggerMainComponent. Builder in the initialize method

@SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {

    this.provideMainViewProvider = MainModule_ProvideMainViewFactory.create(builder.mainModule);

    this.mainPresenterProvider = MainPresenter_Factory.create(provideMainViewProvider);

    this.mainActivityMembersInjector = MainActivity_MembersInjector.create(mainPresenterProvider);
  }
Copy the code

And injectMembers method MainActivity_MembersInjector

@Override
  public void injectMembers(MainActivity instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    instance.mainPresenter = mainPresenterProvider.get();
  }
Copy the code

The MainPresenter_Factory obtains the MainContract.View object from the MainModule_ProvideMainViewFactory get method, The MainModule_ProvideMainViewFactory get method is passed through the provideMainView method of the mainModule passed in. Finally, call injectMembers of MainActivity_MembersInjector in the DaggerMainComponent Inject method implementation, InjectMembers assigns the mainPresenter instantiated by the MainPresenter_Factory get method to the mainPresenter in the MainActivity. This implements the instantiation of mainPresenter.

There are two ways to find whether a parameter annotated with @inject can be injected.

The first way is to look at the constructor directly and instantiate it directly if it has @inject annotations;

The second way is to look at the @Provides in the @Module annotation class to see if there are any needed dependencies.

Note: If the constructor with @inject needs additional parameters, search in the same way.

Don’t look at the source code explanation is really a bit around the mouth, interested in the article can refer to see more detailed instructions.

RxJava

RxJava is a library based on event flow to achieve asynchronous operation, simple logic, elegant implementation, simple to use and so on are the advantages of RxJava. Rxjava is based on an extended observer schema that includes four roles:

role role
Observable Generate events
An Observer Receives the event and gives the response action
Subscribe Connect the observed with the observer
Event The carrier of communication between the observed and the observer

The observed sends the event to the observer via subscription, and the observer receives the event and performs the corresponding action. Observable operators commonly used in Observables

  • ObserveOn: The main function is to specify which thread the Observer should execute on. Multiple executions will be switched.
  • SubscribeOn: Specifies which thread itself (Observable) executes on. If multiple calls are made, only the first call takes effect. Subsequent calls do not switch, regardless of the location of the call. In addition to specifying its own execution location, you can also specify the execution location of doOnSubcribe.
  • DoOnSubscribe: method that is called before the event is subscribed, and if this method is followed by the subscribeOn method, it is also switched to a new thread for execution.
  • DoOnNext: Callback method before the observer is notified, called before onNext() is executed.
  • Compose: operates on the current observer and returns a new observer. Unlike Map, which changes the events and sequences posted by the observer, Compose operates directly on the current Observable.
  • Map: Converts the observed object into a new observed object and sends it to the observer. The observer will receive the new observed object and process it.
  • Subcribe: Connects the observer to the observed. The observer must subscribe to the observed using Subcribe in order to receive the data sent by the observed. There are some methods that can be used by the observer to combine, including onNext, onError, and onCompleted. If no parameters are passed, only the subscription will occur and the observer will receive no data or notifications.

EventBus

The main function of EventBus is to simplify communication between components. It also uses the observer mode to effectively decouple event sending and receiving. It mainly includes the subscriber of the event (receiver) and the publisher of the event (sender), and realizes the communication between the two by passing the event. The basic usage is: first, define an event class to pass events; Secondly, it is necessary to register both subscribers and publishers, and cancel registration when page destruction is not needed. Send event By calling the POST method, the sent event is saved to the event queue. The receiver receives an event class object via the @SUBSCRIBE annotation, specifying the thread model and processing accordingly. There are four types of threading models:

  • POSTING (the default) means that the event handler thread is in the same thread as the POSTING thread.
  • MAIN means that the thread of the event handler is on the MAIN thread, so time-consuming operations cannot be performed there.
  • BACKGROUND indicates that the event handler thread is in the BACKGROUND thread and therefore cannot perform UI operations. If the thread that issued the event is the main thread, the event handler will start a background thread. If the thread that issued the event is a background thread, the event handler will use this thread.
  • ASYNC means that no matter which thread the event is published on, the event handler will always create a new thread to run and also cannot perform UI operations.

If you want to receive an event after the event is sent, you need to use sticky events. Sticky events need to be sent through the postSticky method. To receive sticky events, you need to add sticky=true in annotations.

The above is the latest learning of some knowledge, I hope to give you help.