RecyclerView -- give you a non-card sliding list

Keywords: Mobile Android Gradle ButterKnife network

https://www.jianshu.com/p/519bb23987ca

 

What will you learn after reading this article?

  • RecyclerView adds a head, a tail, or a view somewhere in the list list
  • RecyclerView+SwipeRefreshLayout for drop-down refresh
  • Paging Load Data
  • List optimization scheme
  • Use Glide to load pictures, press the back key while sliding, and App crash bounces off.

Add Dependency

    //recyclerview
    compile 'com.android.support:recyclerview-v7:25.1.1'
    //glide
    compile 'com.github.bumptech.glide:glide:3.7.0'

    //butterknife notices that you need to add code in three third places
    //Add at bottom inside 1 module gradle
    compile 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    //Add top inside 2 module gradle
    apply plugin: 'com.jakewharton.butterknife'
    //3 Add in project gradle
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
        classpath 'com.jakewharton:butterknife-gradle-plugin:8.5.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

Add view anywhere in RecyclerView

There are three functions in RecyclerView:

  1. getItemCount -- Gets the total number of Items in the list

  2. getItemViewType(int position) -- Determines which type of layout to use, returns an int flag position, which is passed to the second parameter of onCreateViewHolder.
    In general, there are many Items in a list, each Item can be its own custom layout and each has a unique location. You can specify the layout type of Item that this position will return by using the position flag in the Item.For example:

@Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return TYPE_HEAD;
        } else if (position + 1 == getItemCount()) {
            return TYPE_FOOTER;
        } else {
            return TYPE_ITEM;
        }
    }

3.onCreateViewHolder(ViewGroup parent, int viewType) renders a specific ViewHolder based on the layout type returned for each position returned by the getItemViewType.For example:

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEAD) {   
            View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_head, parent, false);
            return new HeadViewHolder(view);
        } else if (viewType == TYPE_ITEM) {
            View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_base, parent, false);
            return new ItemViewHolder(view);
        } else if (viewType == TYPE_FOOTER) {
            View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_discover_foot, parent, false);
            return new FootViewHolder(view);
        }
        return null;
    } 

RecyclerView+SwipeRefreshLayout for drop-down refresh

The xml is laid out as follows

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

        <android.support.v7.widget.RecyclerView
            android:id="@+id/discover_recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical" />
    </android.support.v4.widget.SwipeRefreshLayout>

usage

 //Show animation when entering the interface
 swipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
                swipeRefreshLayout.setRefreshing(false); 
            }
        });

//Load refresh data each time a drop-down refresh occurs
        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                if (!isLoading) {
                    isLoading = true;
                    data.clear();
                    getData();
                }
            }
        });

Drop-down data refresh using SwipeRefreshLayout and pull-up loading data using RecyclerView

    public abstract static class OnScrollListener {
       //The newState parameters are:
       //  SCROLL_STATE_TOUCH_SCROLL(1) is scrolling      
       // SCROLL_STATE_FLING(2) Throw your finger (slide it hard before leaving the screen)      
       // SCROLL_STATE_IDLE(0) Stop Scrolling     
        public void onScrollStateChanged(RecyclerView recyclerView, int newState){}

       //When scrolling, it calls back until it stops scrolling.Callback once on Click
        public void onScrolled(RecyclerView recyclerView, int dx, int dy){}
    }

Paging Load Data & List Optimizations (Ideological Programming)

Paging load:
The reality is that each time you pull up, and then add the data into the list collection, you get control of the specific data, that is, from the page number, each time you pull up, you add the page number to the request parameter, and each time you pull down, you clear the data from the list collection, restore the page to its original 1, and put the requested data into the list.

List optimization scheme:
1. Layout as little component nesting as possible, use LinearLayout as much as possible, and use RelativeLayout as little as possible, since RelativeLayout renders require more resources.
2. Picture optimization, it is recommended to use existing picture frames, such as Glide, Picasso, Fresco, ImageLoader, etc. open source framework, because it encapsulates the picture cache mechanism well, and the picture cache will be recycled first when it is not used or when it is used less frequently.
3. Picture loading. When the list slides, display the pictures with placeholder pictures, or the pictures are not displayed at all for processing. Wait until the sliding stops before loading.This demo uses Glide, combined with RecyclerView.OnScrollListener, to handle picture loading.See demo source code specifically.
4. Every time a page loads data, when is the data added to the List (or when is the best time for the network to request data). After I studied the gliding fluency of bilibilibili Android App and other App lists, bilibili is the least gliding fluent. Why?This is actually due to the start time of network requests for data when paging.Handled in the onScrolled sliding event of RecyclerView.OnScrollListener.
There is a 5 in the code below, which is the key to smooth code sliding, or it may or may not be 5, written as you need it.

@Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int lastVisibleItemPosition = linearLayoutManager.findLastVisibleItemPosition();
                if (lastVisibleItemPosition + 5 >= adapter.getItemCount()) {
                    boolean isRefreshing = swipeRefreshLayout.isRefreshing();
                    if (isRefreshing) {
                        adapter.notifyItemRemoved(adapter.getItemCount());
                        return;
                    }
                    if (!isLoading) {        
                        isLoading = true;
                        getData();
                    }
                }
            }

Advantages of this optimization: Sliding is particularly smooth. Disadvantages: Loading start time may vary depending on the size of the screen, and you may not experience the animation of pull-up loading data (pull-up loading more.) This is hard to see, but you can still see when the network is slow.

Use Glide to load pictures, press the back key while sliding, and App crash bounces off.

The list sliding optimization I just mentioned, and I just used a Glide to load the pictures myself. You can see that, in a flash, when I press the back key to exit, App crash bounces, why?Why?Why?Why?due to "You cannot start a load for a destroyed activity".

 

The reason for this is that I stopped loading the pictures when I slid over there and loaded the pictures when I stopped, "You cannot start a load for a destroyed activity," which means activity was destroyed when you pressed the back key and the Glide image processing event for that scrolling event is still running.

  mOnScrollListener = new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                switch (newState) {
                    case SCROLL_STATE_IDLE:
                        Glide.with(MainActivity.this).resumeRequests();
                        break;
                    case SCROLL_STATE_DRAGGING:
                    case SCROLL_STATE_SETTLING:
                        Glide.with(MainActivity.this).pauseRequests();
                        break;
                }
            }

Solve the problem:

  1. Try to judge before each Glide is used, and write the following in the activity's onDestory method to solve the problem!Blog links: http://blog.csdn.net/a940659387/article/details/50555327
if(Util.isOnMainThread()) {
            Glide.with(this).pauseRequest();
        }
  1. Try changing this to getApplicationContext() and still crash when each Glide is used!Blog links: http://www.jianshu.com/p/4a3177b57949
Glide.with(this).resumeRequests();  
  1. The recommended success I use is the perfect oknice approach, not from Glide, but from scrolling.Get something: Change your mind. Don't keep tangling with Glide.
 @Override
    protected void onPause() {
        recyclerView.removeOnScrollListener(mOnScrollListener);
        super.onPause();
    }

Provides ideas for learning and use only, and must be implemented according to its own business logic

Source Address
https://github.com/androidHRTZ/SuperRecyclerView.git

Please start with author details and the source of this article. Thank you.



Author: rivc
Link: https://www.jianshu.com/p/519bb23987ca
Source: Short Book
Copyright belongs to the author.For commercial reprinting, please contact the author for authorization. For non-commercial reprinting, please indicate the source.

Posted by severndigital on Sun, 01 Dec 2019 12:02:03 -0800