base (5) base Fragment Packaging

Keywords: Android Fragment ButterKnife xml

Let's start with two sentences.

First of all, I would like to apologize to you, before the end of the BaseActivity part and the ButterK part are somewhat excited, after the blog was sent out, I forgot to submit the code to git. When I opened the project, I saw all the green and blue files. It's really embarrassing. I have submitted them, so I can check them if necessary. My code is perfect with blogging, so I hope today's final reminder to submit, otherwise... Don't beat me, I'm afraid of pain.
MyBaseApplication (https://github.com/BanShouWeng/MyBaseApplication)

text

Fragment Basic Method

As mentioned earlier, the last article has already finished encapsulating BaseActivity. Of course, it is only some basic operations. In the follow-up process, it will surely be improved gradually with the application of new functions. What we are studying today is the encapsulation of Base Fragment. Of course, as mentioned in the previous paragraph, the content of this part is also temporary basic content. It does not mean that today's content has been completed, and there will be no need for any modification in Base Fragment in the future, so it varies from person to person and from project to project. Before that, we had to analyze and paste the code. Today, we have to change our routine and start a big one.

package com.banshouweng.mybaseapplication.base;

import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.banshouweng.mybaseapplication.R;

/**
 * <Starting from scratch for an Android project
 *@author Half-life Pulsatilla
 *@Blog:
 *@ CSDN http://blog.csdn.net/u010513377/article/details/74455960
 *@ Brief book http://www.jianshu.com/p/1410051701fe
 */
public class BaseFragment extends Fragment {
    private OnFragmentInteractionListener mListener;
    private Unbinder unbinder;

    public BaseFragment() {
        // Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @return A new instance of fragment BaseFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static BaseFragment newInstance() {
        BaseFragment fragment = new BaseFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        unbinder = ButterKnife.bind(this, view);
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_base, container, false);
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        unbinder.unbind();
    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
    }
}

Carefully, I may find that I changed the package name and filled in banshouweng. It is true that all the demos I searched for are of this kind. There is no way. The demos I searched for online have similar personal promotion. How can I not bear to add one to myself? Hey hey.
Okay, get to the point.
Above all, after creating a block fragment, AS automatically generates a series of methods. Of course, if you also create a block fragment, it should be more than my content, because the above post has been screened by me, after all, you let a lazy person, come up to see so many code, anyway, I personally can not bear it.
Now let's talk about all the code I left behind.

  1. BaseFragment
    Constructing method is the only method that is not used for the time being. Its purpose is simply to compare with the following new Instance. Of course, if the getArgument parameter in onCreate is not applicable, it can be passed by constructing method, but it is seldom used now.
  2. newInstance
    The function here is the same as the above method of construction. After all, we can see that there is only one method of construction. As to why it is popular to use new Instance instead of the method of construction, the main purpose is to decouple. Well, I also hate these very tall professional words. As far as I know, one of the best ways to use it is reuse. If we use the constructor, we can only create an object. If we put the object created in the new Instance into a global variable and make a blank judgment, you will find that we can use the same object on many occasions, without passing parameters or even retaining the state. . (The difference between new Instance and construction is not limited to Fragment.)
  3. onCreate
    It is used to get argument, that is, parameter acquisition passed from Activity, and no other use has been found for the time being.
  4. onCreateView and onViewCreated (not in the code above) and onDestroyView
    OnCreateView is executed before view creation. onViewCreated is executed after view creation. It is a pair. It is usually used to parse layout. Of course, if you look at my last blog, you should see a paragraph written in it. About ButterKnife.findById used in Fragment, the view parameter can be replaced by the parsed layout here. This method makes it possible to Use is in onView Created, and after the onView Created method runs, we can operate on our control, otherwise it is easy to have null pointer exception. The use of onCreateView and onDestroyView is the binding and unbinding of ButterKnife, as shown in the previous code.
  5. onAttach
    Sometimes using get Activity in Fragments will report null pointer exceptions, so we need onAttach to help, because you will see that its parameter is Context, as long as it is saved, it can be directly invoked in use to solve this problem. However, because of this operation we do when encapsulating BaseFragment, we usually use Context directly, so we don't need to call it anymore.
  6. onDetach
    The onAttach method above can be counted as a pair. The Activity binding method and the onDetach method are implemented when the binding is unbounded. The operation of this method is to empty the parameters associated with the Activity used in the whole Fragment to prevent the occurrence of OOM.
  7. OnFragment Interaction Listener and onButton Pressed
    This part is also intended to write their own content, but now AS has proposed solutions for us. The function is to pass the parameters in Fragment to Activity, which is generated by AS, which transfers Uri. When we use it, we can define the content to be delivered by ourselves. We can also write and add other abstract methods in the interface, and we can not write them when we don't need them. The purpose of onButtonPressed is to tell us how to use this part of the code, and to use it flexibly according to your own needs.

Base Fragment Packaging

In fact, this part is complex, but also relatively simple. After all, we have encapsulated the BaseActivity before. Many methods are common. So the corresponding part, we just need to paste it and make some modifications. So here, I will write out some of our differences. The other parts, let's take a look at the code.

Method encapsulation

When we write BaseActivity, we start with layout. To be fair, we start with method encapsulation.
Of course, if you really think that my arrangement is what is called fair, it only means that you are too simple, as a lazy person like us, what time to consider what is fair, how good to sleep at that time. So there's only one reason for this arrangement, and that's because the encapsulation of the method is simpler.
But before encapsulating the method, we have one thing to deal with, which is what we just said in onAttach. And for this part, if you have read my previous blog, you will know that when you write the encapsulation of Base Activity method, when you talk about why you create two objects, Context and Activeness, in order to unify with the direction referenced in Fragments, whether these two objects have other functions remains to be explored in the future, but it is definitely necessary in Fragments. .
Create it if necessary. Code it:

    /**
     * Context information for delivery
     */
    public Context context;
    public Activity activity;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context.getApplicationContext();
        activity = (Activity) context;
    }

this completes the acquisition of Context and Activity. Later, the use of Fragment depends heavily on these two objects. this part of my personal advice is to copy the methods in BaseActivity directly, and then you will see individual errors, and then add "activity." this is to determine whether the method is related to the bound activity. Some are replaced by activities, while others are replaced by context, which completes the encapsulation of methods, such as:

    //Error reporting section
    public void startActivity(Class<?> clz) {
        startActivity(new Intent(this, clz));
    }

    //After modification
    public void startActivity(Class<?> clz) {
        startActivity(new Intent(context, clz));
    }


    //Before revision
    case R.id.base_back:
                if (isResetBack) {
                    onClickBack.clickBack();
                } else {
                    finish();
                }
                break;
    //Revised
    case R.id.base_back:
                if (isResetBack) {
                    onClickBack.clickBack();
                } else {
                    activity.finish();
                }
                break;

So much code can be pasted directly, including network monitoring and progress bar parts, of course, if really lazy, progress bar parts can not be copied, but in the need to use Fragments, using the interface OnFragmentInteraction Listener mentioned above directly call the progress bar in BaseActivity.
Finally, I suggest that all the method calls performed by BaseActivity in onCreate should be placed in onViewCreated method and unnecessary null pointers should be placed.

Title

Looking at the title, you should know that we've already wrapped up the method, and I'm quite fond of this lazy task.
But unfortunately, this time it took some thought to fall on Title, but fortunately, the difficulty is limited, so I am very touched by such lazy people.

Title Packaging

Well, seeing Title, I think of the three situations in the first blog. It's really troublesome to talk about. There are still many factors to consider. Rewrite a real 10,000 reluctant, or some people will think that we can directly copy the layout of BaseActivity and paste it into the layout of BaseFragment. It's also a way to think about it, but it's a matter of time. Where do we need this Title layout (although I haven't thought about where we will need it yet)? We still need to find the layout and copy it. How can lazy people like me tolerate it?
So there's the title above, that's Title encapsulation. You can see it correctly. The layout can also be encapsulated, and it's not difficult. Let's start now.
First, you need to create an xml layout. Of course, the type you choose is Layout. I call this layout title_layout, which is very mindless. Then I cut and paste the Title layout in BaseActivity into this layout.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/title_height"
    android:background="@color/colorPrimary">

    <ImageView
        android:id="@+id/base_back"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:padding="@dimen/size_13"
        android:src="@mipmap/back"
        android:tint="@android:color/white" />

    <TextView
        android:id="@+id/base_title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="@string/title"
        android:textColor="@android:color/white"
        android:textSize="@dimen/size_20" />

    <ImageView
        android:id="@+id/base_right_icon2"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_toLeftOf="@+id/base_right_icon1"
        android:contentDescription="@string/second_function_key"
        android:padding="@dimen/size_13"
        android:src="@mipmap/add"
        android:tint="@android:color/white"
        android:visibility="gone" />

    <ImageView
        android:id="@+id/base_right_icon1"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:contentDescription="@string/first_function_key"
        android:padding="@dimen/size_13"
        android:src="@mipmap/more"
        android:tint="@android:color/white"
        android:visibility="gone" />

    <TextView
        android:id="@+id/base_right_text"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentRight="true"
        android:gravity="center"
        android:text="@string/make_sure"
        android:textColor="@android:color/white"
        android:textSize="@dimen/size_17"
        android:visibility="gone" />
</RelativeLayout>

But apparently, cut it down, then there is no Title layout in BaseActivity. What can we do? Let's witness the magic of Title's crazy turn. In the position of Title before BaseActivity layout, write the following code:

    <include
            android:id="@+id/base_title_layout"
            layout="@layout/title_layout"></include>

Did you see the Title layout that we cut back on show again? As for what include is and how to use it, I'm a novice bird. I'm not going to talk about it here, but I'm going to link it directly. Let's go and see how the gods explain it. That's right. It's our God Guo Linguo. Android Best Performance Practice (IV) - Layout Optimization Skills . Of course, we can see the optimization part in addition to include, merge and ViewStub, you can see Guo Shen's blog to understand for yourself, I should also use the optimization of these two parts in the back of the blog here, but I lazy you know, when not used, how can I write in my own blog, so this part can only be explained in the back.
Good gossip, get the BaseActivity, we should also deal with the layout of BaseFragment, but fortunately because Fragment is also used in the layout of Activity, so since our BaseActivity has a layer of ScrollView nested outside, so the layout of BaseFragment does not need to do anything more, we just need one of them. Layout is OK, the code is as follows:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/base_scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.banshouweng.mybaseapplication.base.BaseFragment">

    <include
        android:id="@+id/base_title_layout"
        layout="@layout/title_layout"></include>

    <LinearLayout
        android:id="@+id/base_main_layout"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:orientation="vertical"></LinearLayout>
</LinearLayout>

Does it look simpler, so that our Title encapsulation is over, of course, the use of include?

Title Correspondence Method

1. Initialization control

The point to note here is that I lazily changed initView to ButterKnife, so in BaseActivity, the following code is available:

    /**
     * Control initialization
     */
    public void initView() {
        baseBack = ButterKnife.findById(activity, R.id.base_back);
        baseRightIcon1 = ButterKnife.findById(activity, R.id.base_right_icon1);
        baseRightIcon2 = ButterKnife.findById(activity, R.id.base_right_icon2);
        baseTitle = ButterKnife.findById(activity, R.id.base_title);
        baseRightText = ButterKnife.findById(activity, R.id.base_right_text);
        baseTitleLayout = ButterKnife.findById(activity, R.id.base_title_layout);
        baseMainLayout = ButterKnife.findById(activity, R.id.base_main_layout);
        baseScrollView = ButterKnife.findById(activity, R.id.base_scroll_view);
    }

And in Base Fragment, remember to change it to the following:

    /**
     * Control initialization
     */
    private void initView() {
        baseBack = ButterKnife.findById(currentLayout, R.id.base_back);
        baseRightIcon1 = ButterKnife.findById(currentLayout, R.id.base_right_icon1);
        baseRightIcon2 = ButterKnife.findById(currentLayout, R.id.base_right_icon2);
        baseTitle = ButterKnife.findById(currentLayout, R.id.base_title);
        baseRightText = ButterKnife.findById(currentLayout, R.id.base_right_text);
        baseTitleLayout = ButterKnife.findById(currentLayout, R.id.base_title_layout);
        baseMainLayout = ButterKnife.findById(currentLayout, R.id.base_main_layout);
        baseScrollView = ButterKnife.findById(currentLayout, R.id.base_scroll_view);
    }

The current Layout is saved in onCreateView. The main reason for this is that if we use activity here, it means that we let ButterKnife look for controls in the Activity bound by Fragment, but our goal is to find them in the current Fragment, so we can't use activity here, we need to replace it with current. TLayout.

2. Title method encapsulation

All the controls have been initialized, so we should encapsulate the methods. In fact, it's only a few methods. We just need to copy them, and the way they are called is exactly the same as the way they are encapsulated in BaseActivity, so that's the end of this part.

ps: In order to prevent the end from being too hasty, I would like to make some additions to BaseActivity at the end. That is, in BaseActivity, we use ScrollView to compatible with some low-resolution mobile phones and prevent page content from being displayed incompletely. But some pages do not have Titles, for example, the home page often does not need to use Title, while I used to use ScrollView in BaseActivity. Think of it as using the setContentView method directly, so there is no corresponding processing, but it ignores that if the setContentView method is used, then the effect of ScrollView will disappear, so a method of hiding header layout is added:

    /**
     * Hidden Header Layout
     */
    public void hideTitle() {
        baseTitleLayout.setVisibility(View.GONE);
    }

Of course, it's not clear whether Fragments need to be used. We can encapsulate them in Base Fragments first, or we can encapsulate them later.

appendix

A Zero Start for an Android Project directory

Posted by suigion on Thu, 13 Jun 2019 11:21:21 -0700