preface

Looking back to the Android years, UI came out, two eyes must be, a Bean and XML, laughing and talking, designers tremble. Oh, don’t worry about this song, just ignore it! Things are different, ah, now always take out a Taobao page, but also the entry is not fixed, but also happy to play? In addition to the miscellaneous technology added, such as burying points, UI frame is getting heavier and heavier, are tears ah! If only we could go back. Come on, my friend, it’s real. It’s not a dream.

In actual combat

Even before, a lot of groundwork had to be done, you had to write XML, right? Bean do you have to write Bean? Can’t get away with rendering logic? So, after today, uh… You still have to write that, but you don’t have to write the rest of the non-business logic. First, let’s take a look at this home page effect.

Renderings are displayed

Complexity does not lose simplicity, simplicity does not lose connotation, this is my friend Mr. Sun’s great masterpiece, and what you see is that I use the program to show it, Mr. Sun, where you are not satisfied, you can say.

Basic introduction to

Without further ado, such a home page, how do we need to do the basic work? Or, what should we do with more complex pages in the future? Here’s a tip: Stop using things like ScrollView. It’s a little bit of a no-no. It’s not something Google wants to see RecyclerView. The RecyclerView view is rendered by Adapter. The original Adapter was a pain in the ass. There were too many repetitions. We should have the idea of encapsulation and provide the most needed parts, leaving the rest alone.

The most popular Adapter library is, I think, BRVAH. How easy is it?

public class QuickAdapter extends BaseQuickAdapter<Status, BaseViewHolder> {
    public QuickAdapter() { super(R.layout.tweet, DataServer.getSampleData()); } @Override protected void convert(BaseViewHolder viewHolder, Status item) { viewHolder.setText(R.id.tweetName, item.getUserName()) .setText(R.id.tweetText, item.getText()) .setText(R.id.tweetDate, item.getCreatedAt()) .setVisible(R.id.tweetRT, item.isRetweet()) .linkify(R.id.tweetText); Glide.with(mContext).load(item.getUserAvatar()).crossFade().into((ImageView) viewHolder.getView(R.id.iv)); }}Copy the code

That’s it. I’ll do it right there.

The library also provides methods for rendering complex views, but it’s still a bit of a hassle to use. Personally, I don’t think it’s not that you don’t write, but that you don’t need to write. You should have a clear division of labor. It’s not good to be too intrusive. So MTRVA was born, let’s not worry about the name.

MTRVA was originally named because the multi-type view inherits the Adapter, but after learning of the limitations of inheritance, it was changed to be presented in combination with the Adapter. It is more appropriately called AdapterHelper because it can work with most Adapters. Processing multi-type views was an original idea and is now just a function point. In fact, it internally takes over the Resources and data sources of Adapter, making it easier and faster to process data without having to worry about resources and data sources. There’s no point in saying anything. Let’s go.

Tips: The full text, and even the library demo, is based on BRVAH.Copy the code

BaseAdapter encapsulation

Since want to cooperate, then always want to add fearless code amount, rest assured, I have considered. Put our basic BaseAdapter, of course you can add others based on your project.

public abstract class BaseAdapter<T extends MutiTypeTitleEntity, K extends BaseViewHolder, H extends RecyclerViewAdapterHelper<T, BaseAdapter>> extends BaseQuickAdapter<T, K> {

    protected H mHelper;

    public BaseAdapter(H helper) {
        super(helper.getData());
        mHelper = helper;
        mHelper.bindAdapter(this);
    }

    @Override
    protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
        return createBaseViewHolder(parent, mHelper.getLayoutId(viewType));
    }

    @Override
    protected int getDefItemViewType(int position) {
        return mHelper.getItemViewType(position);
    }

    public H getHelper() {
        returnmHelper; }}Copy the code

In the constructor, let the Helper unbind the Adapter and return its data source to the Adapter. In the onCreateDefViewHolder method, let the Helper return the registered resource to the Adapter, as well as ItemViewType. At this point, BaseAdapter encapsulation is complete, and there is not much difficulty or code.

XML and Bean

Bean I will not say ha, with the server comrades good communication, well, good communication. Since the Helper takes over the Adapter’s data sources and resources, and then provides its own creation to the Adapter, how is it created, as described in the BaseAdapter wrapper?

public class MyAdapterHelper extends AsynAdapterHelper<MutiTypeTitleEntity, BaseAdapter> {


    public MyAdapterHelper() {
        super(null);
    }

    @Override
    protected void registerMoudle() {... registerMoudle(ItemEntity3.TYPE_3) .level(2) .layoutResId(R.layout.item_3) .register(); . }}Copy the code

At its simplest, this is all you need to do. The workload here is to create one Helper per Adapter, probably because we can reuse it sometimes. Inject the data source in the constructor, or you can pass null as in the example code, which creates an empty collection by default. We can register an XML view for each ItemType, just as there used to be one XML view for each Activity. Of course, resource registration is much more than that. For example, our library divides an ItemType view into three sections: header, data, and footer. For a single Type, you can switch between data, Loading, Empty and error without any pressure. There are many others, I will not introduce, otherwise the length is too long, many mobile phone party to scold niang.

Return to the Adapter

After the Helper creates the resource, it always returns to the Adapter. In the Base wrapper, we already know how the Helper binds to the Adapter. Take a look at the Adapter sample code to make it more intuitive.

public class MyAdapter extends BaseAdapter<MutiTypeTitleEntity, BaseViewHolder, MyAdapterHelper> {


    private CommonHeadEntity entity1Header = new CommonHeadEntity(ItemEntity1.HEADER_TITLE, ItemEntity1.TYPE_1);
    private CommonHeadEntity entity2Header = new CommonHeadEntity(ItemEntity2.HEADER_TITLE, ItemEntity2.TYPE_2);
    private CommonHeadEntity entity4Header = new CommonHeadEntity(ItemEntity2.HEADER_TITLE, ItemEntity4.TYPE_4);
    private CommonFooterEntity entity1Footer = new CommonFooterEntity(Constants.EXPAND, ItemEntity1.TYPE_1);

    public MyAdapter() { super(new MyAdapterHelper()); } @Override protected void convert(BaseViewHolder helper, MutiTypeTitleEntity item) { int itemType = item.getItemType();  switch (itemType) {case ItemEntity1.TYPE_1:
                renderEntity1(helper, (ItemEntity1) item);
                break; .case ItemEntity1.TYPE_1 - RecyclerViewAdapterHelper.HEADER_TYPE_DIFFER:
            case ItemEntity2.TYPE_2 - RecyclerViewAdapterHelper.HEADER_TYPE_DIFFER:
            case ItemEntity4.TYPE_4 - RecyclerViewAdapterHelper.HEADER_TYPE_DIFFER:
                renderHeader(helper, (CommonHeadEntity) item);
                break;
            case ItemEntity1.TYPE_1 - RecyclerViewAdapterHelper.FOOTER_TYPE_DIFFER:
                renderFooter(helper, (CommonFooterEntity) item);
                break; } } private void renderEntity1(BaseViewHolder helper, ItemEntity1 item) { helper.setImageResource(R.id.item_1_img, item.getImg()); helper.setText(R.id.item_1_title, item.getTitle()); helper.setText(R.id.item_1_content, item.getContent()); helper.setText(R.id.item_1_time, item.getTime()); helper.setText(R.id.item_1_time_flag, item.getTimeFlag()); }... private void renderHeader(BaseViewHolder helper, CommonHeadEntity item) { helper.setText(R.id.title, item.getTitle()); } private void renderFooter(BaseViewHolder helper, final CommonFooterEntity item) { final inttype = item.getItemType() + RecyclerViewAdapterHelper.FOOTER_TYPE_DIFFER;
        final TextView footer = helper.getView(R.id.item_footer);
        footer.setText(item.getTitle());
        footer.setOnClickListener(v -> {
            if (Constants.EXPAND.equals(item.getTitle())) {
                item.setTitle(Constants.FOLD);
                mHelper.foldType(type.false);
            } else {
                item.setTitle(Constants.EXPAND);
                mHelper.foldType(type.true); } footer.setText(item.getTitle()); }); }... public void notifyType1(List<ItemEntity1> itemEntity1s) { mHelper.notifyMoudleDataAndHeaderAndFooterChanged(entity1Header, itemEntity1s, entity1Footer, ItemEntity1.TYPE_1); }... }Copy the code

This is a complicated view, this little bit of code, and you’re right. The core method is the convert() method, which renders the view corresponding to the ItemType, just as there are XML, beans, and render logic corresponding to different activities. I won’t say anything about the Render () method, because I think everyone is going to throw up. Helper supports injection of a single Type, even down to a small Type within a single Type, such as header, in addition to the entire data source. It’s so cool. No, no, no. The notifyType1() method is used to inject data corresponding to type ItemEntity1.type_1 because it represents all the small types. This is also the same as wrapping the image loading library with a utility class. If the library changes, you won’t want to run away, will you?

conclusion

Is that the end of it? Is that the end of a complex interface? Tease me? That simple? Well, dude, that’s really it, I’m not going to tell you I wrote this interface in kjadadNkdkladllllll, sorry, LET me fix my hair. To be honest, the reduction in work with BRVAH is really too much. If you don’t like it, you can write the same interface as native, and use BRVHA+MTRVA timing comparison, I don’t want to calculate the code quality problem with you. You can even use Adapter libraries that specialize in multiple types of complex views for the same effect, the same functionality, and time comparison. Make use of the include and merge tags, and you will get some unexpected results. Here we are not talking about how fast you type code, but an overall efficiency problem, short time, high quality, simple process, there is no reason not to use it?

Here I would like to thank Mr. Sun for his design and all the people who have been supporting me. Thank you very much. There’s really just a little bit of flow to using a library, it’s very simple. For more information, see the github user guide.

portal

Github:github.com/crazysunj/M…