Android adapter mode, handwritten ListView experience adapter

adapter mode

1. Small scenes of life

In our daily life, we convert wind energy into our electrical energy. If we directly obtain wind energy, can we make our lamps shine? It's not possible, right, so these are two incompatible things. Wind energy cannot directly light up our light bulbs, so what should we do? We can only convert our wind energy into our electrical energy through a generator, and then use the electrical energy to light the lights. Therefore, our generator is equivalent to an adapter. It combines two incompatible interfaces and makes them compatible together. Macroscopically In other words, wind energy lights up our light bulbs.

Insert image description here

2. Adapter pattern definition

​ Adapter Pattern serves as a bridge between two incompatible interfaces. This type of design pattern is a structural pattern, which combines the functionality of two independent interfaces. This pattern involves a single class that is responsible for adding independent or incompatible interface functionality.

3. Small code case

Here we give an example of a computer connecting to a monitor via HDMI via USB.

Insert image description here

/**
 * 目标
 */
public interface Target {
    
    
    void method();
}
/**
 * 具体目标是需要一个HDMI的接口
 */
public class ConcreteTarget implements Target{
    
    
    @Override
    public void method() {
    
    
        Log.w("simple ConcreteTarget", "我需要使用HDMI接口");
    }
}
/**
 * 源数据,电脑和屏幕连接
 */
public class Adaptee {
    
    
    public void method2() {
    
    
        Log.w("simple Adatee", "我需要使用USB接口");
    }
}
/**
 * 桥梁连接,继承自源数据Adaptee,并且实现目标数据的接口,意思是两边都不落下,作为桥梁
 */
public class Adapter extends Adaptee implements Target{
    
    
    @Override
    public void method() {
    
    
        //拿到源数据
        super.method2();
        //这句日志可以理解为转接头,源数据--->目标数据
        Log.w("simple Adapter", "使用了USB转HDMI线,现在可以使用在HDMI线上了");
    }
}

The adapter pattern written above can be understood as the adapter pattern at the class level. Class adapters are not very flexible.

Let's modify it

/**
 * 桥梁连接,继承自源数据Adaptee,并且实现目标数据的接口,意思是两边都不落下,作为桥梁
 */
public class Adapter extends Adaptee implements Target {
    
    
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
    
    
        this.adaptee = adaptee;
    }

    @Override
    public void method() {
    
    
        //拿到源数据
        adaptee.method2();
        //这句日志可以理解为转接头,源数据--->目标数据
        Log.w("simple Adapter", "使用了USB转HDMI线,现在可以使用在HDMI线上了");
    }
}

Test code:

public class TestActivity extends AppCompatActivity {
    
    


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Adaptee adaptee = new Adaptee();

        Adapter adapter = new Adapter(adaptee);
        adapter.method();
    }
}

From the results, it can be seen that the operation was successful, which means that the adapter successfully bridged the USB and HDMI interfaces.

Insert image description here

summary:

  1. Two incompatible contents are bridged and integrated and connected through the mediator Adapter.
  2. If you want to convert one class into another class, but the two classes are incompatible, and you want them to work together, then it is more suitable to use our adapter pattern to improve the reuse of classes.

4. Adapter mode of RecyclerView

Let's look at the picture below. Our app's list will have a lot of data. The data is stored in the collection. But our data, that is, our collection cannot be directly added to our ViewGroup. Why? It is a ViewGroup, because the list will definitely not have only one subview, and the data cannot be directly added to our view for display through addView.

So we need to make a transfer and an adapter. What does it do? It changes the data and changes the data in the collection into corresponding Views. Then these Views can be added to our view through addView. The view above went,

Insert image description here

Next we write a Demo to get a feel for the adapter:

Activity for testing

public class TestActivity extends AppCompatActivity {
    
    
    private RecyclerView recyclerView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recyclerview);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);

        //构建源数据,
        List<String> data = new ArrayList<>();
        data.add("111");
        data.add("222");
        data.add("333");
        MyAdapter myAdapter = new MyAdapter(this, data);
        recyclerView.setAdapter(myAdapter);
    }
}

adapter

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
    
    
    private Context mContext;
    private List<String> mData;

    public MyAdapter(Context mContext, List<String> mData) {
    
    
        this.mContext = mContext;
        this.mData = mData;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    
    
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_test, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    
    
        String data = this.mData.get(position);
        holder.textView.setText(data);
    }

    @Override
    public int getItemCount() {
    
    
        return mData.size();
    }

    public static class MyViewHolder extends RecyclerView.ViewHolder {
    
    
        TextView textView;

        public MyViewHolder(@NonNull View itemView) {
    
    
            super(itemView);
            textView = itemView.findViewById(R.id.textview);
        }
    }
}

xml layout of item subview

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:textSize="30sp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="111" />
</LinearLayout>

xml of parent layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    >
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

Final running result:

Insert image description here

This is a classic example of the adapter pattern, which is also very commonly used. The data in the collection is transferred through the adapter, and then the adapter addView is used.

5. Handwritten ListView experience adapter mode

Let's customize an adapter by hand to experience the use of the adapter mode.

/**
 * 手写简单的ListView,不考虑复用
 */
public class TestListView extends ScrollView {
    
    
    private LinearLayout mContainer;
    private ListAdapter mAdapter;

    public TestListView(Context context) {
    
    
        super(context, null);
    }

    public TestListView(Context context, AttributeSet attrs) {
    
    
        super(context, attrs, 0);
        mContainer = new LinearLayout(context);
        mContainer.setOrientation(LinearLayout.VERTICAL);
        super.addView(mContainer);
    }

    public TestListView(Context context, AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        mContainer = new LinearLayout(context);
        mContainer.setOrientation(LinearLayout.VERTICAL);
        super.addView(mContainer);
    }

    public void addView(View child) {
    
    
        mContainer.addView(child);
    }

    public void setAdapter(ListAdapter listAdapter) {
    
    
        this.mAdapter = listAdapter;
        int count = mAdapter.getCount();
        for (int i = 0; i < count; i++) {
    
    
            View childView = mAdapter.getView(i, mContainer);
            mContainer.addView(childView);
        }

    }
}

First customize an abstract class parent class adapter to simulate the two methods of ListView.

public abstract class ListAdapter {
    
    
    //获取多少条
    public abstract int getCount();
    //获取View
    public abstract View getView(int position, ViewGroup viewGroup);
}

Implementation class

public class MyAdapter extends ListAdapter {
    
    
    private Context mContext;
    private List<String> mItems;

    public MyAdapter(Context mContext, List<String> mItems) {
    
    
        this.mContext = mContext;
        this.mItems = mItems;
    }

    @Override
    public int getCount() {
    
    
        return mItems.size();
    }

    @Override
    public View getView(int position, ViewGroup viewGroup) {
    
    
        TextView itemView = (TextView) LayoutInflater.from(mContext).inflate(R.layout.item_simple3, null);
        itemView.setText(mItems.get(position));
        return itemView;
    }
}

Test class

public class TestActivity extends AppCompatActivity {
    
    
    TestListView testListView;
    List<String> mData;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testListView = findViewById(R.id.testView);
        mData = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
    
    
            mData.add(i + "");
        }
        MyAdapter myAdapter = new MyAdapter(this, mData);
        testListView.setAdapter(myAdapter);
    }
}

xml layout of activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <com.example.myapplication.TestListView
        android:id="@+id/testView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.example.myapplication.TestListView>

</LinearLayout>

xml layout of itemView

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

</TextView>

Test Results

Insert image description here

Guess you like

Origin blog.csdn.net/weixin_46039528/article/details/130569857