Design pattern 6: Adapter pattern: Is the adapter pattern in ListView a class adapter or an object adapter?

Source code of several important classes

The following is the source code of Android 6.0 version.

/frameworks/base/core/java/android/widget/Adapter.java

Adapter.java

public interface Adapter {
    
    

	...
	
    int getCount();   
    
    Object getItem(int position);
    
    View getView(int position, View convertView, ViewGroup parent);
    
    boolean isEmpty();
    ...
}

ListAdapter.java

/frameworks/base/core/java/android/widget/ListAdapter.java

public interface ListAdapter extends Adapter {
    
    
    public boolean areAllItemsEnabled();
    boolean isEnabled(int position);
}

BaseAdapter.java

/frameworks/base/core/java/android/widget/BaseAdapter.java

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    
    
    private final DataSetObservable mDataSetObservable = new DataSetObservable();

	...
    
    public void registerDataSetObserver(DataSetObserver observer) {
    
    
        mDataSetObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
    
    
        mDataSetObservable.unregisterObserver(observer);
    }
    
	
    public void notifyDataSetChanged() {
    
    
        mDataSetObservable.notifyChanged();
    }

	...

    public boolean isEnabled(int position) {
    
    
        return true;
    }

	...

    public int getViewTypeCount() {
    
    
        return 1;
    }
    
    public boolean isEmpty() {
    
    
        return getCount() == 0;
    }
}

ArrayAdpater.java

/frameworks/base/core/java/android/widget/ArrayAdapter.java

public class ArrayAdapter<T> extends BaseAdapter implements Filterable, ThemedSpinnerAdapter {
    
    
    private List<T> mObjects;
    ...
    public ArrayAdapter(Context context, @LayoutRes int resource, @NonNull List<T> objects) {
    
    
        this(context, resource, 0, objects);
    }
    
    public ArrayAdapter(Context context, @LayoutRes int resource, @IdRes int textViewResourceId,
            @NonNull List<T> objects) {
    
    
        mContext = context;
        mInflater = LayoutInflater.from(context);
        mResource = mDropDownResource = resource;
        mObjects = objects;
        mFieldId = textViewResourceId;
    }
    
    public int getCount() {
    
    
        return mObjects.size();
    }
 
    public T getItem(int position) {
    
    
        return mObjects.get(position);
    }
    
    public View getView(int position, View convertView, ViewGroup parent) {
    
    
        return createViewFromResource(mInflater, position, convertView, parent, mResource);
    }
    
    private View createViewFromResource(LayoutInflater inflater, int position, View convertView,
            ViewGroup parent, int resource) {
    
    
        View view;
        TextView text;

        if (convertView == null) {
    
    
            view = inflater.inflate(resource, parent, false);
        } else {
    
    
            view = convertView;
        }

        try {
    
    
            if (mFieldId == 0) {
    
    
                //  If no custom field is assigned, assume the whole resource is a TextView
                text = (TextView) view;
            } else {
    
    
                //  Otherwise, find the TextView field within the layout
                text = (TextView) view.findViewById(mFieldId);
            }
        } catch (ClassCastException e) {
    
    
            Log.e("ArrayAdapter", "You must supply a resource ID for a TextView");
            throw new IllegalStateException(
                    "ArrayAdapter requires the resource ID to be a TextView", e);
        }

        T item = getItem(position);
        if (item instanceof CharSequence) {
    
    
            text.setText((CharSequence)item);
        } else {
    
    
            text.setText(item.toString());
        }

        return view;
    }
}

The specific use of ArrayAdapter

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class Demo13Activity extends Activity {
    
    
    private ListView lv;
    private ArrayList<String> list = new ArrayList<String>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        lv = (ListView)findViewById(R.id.listview);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_expandable_list_item_1,
                getData());
        lv.setAdapter(adapter);
    }
    
    private ArrayList<String> getData()
    {
    
    
        list.add("180平米的房子");
        list.add("一个勤劳漂亮的老婆");
        list.add("一辆宝马");
        list.add("一个强壮且永不生病的身体");
        list.add("一个喜欢的事业");
        return list;
    }
}

ListView.java

/frameworks/base/core/java/android/widget/ListView.java

public class ListView extends AbsListView {
    
    
	......
	
    @Override
    public void setAdapter(ListAdapter adapter) {
    
     //这里需要的是ListAdapter接口类型的入参
    ...
	}
	......
}

object adapter pattern

The three roles of the class adapter pattern:

  • Destination Interface(dst: destination target, destination)
  • source class (src:source source)
  • adapter

ListView is used as a client, and the target interface it needs is the ListAdapter interface.
Source class is DataSource: ArrayList<String>
Adapter is ArrayAdapter

ArrayAdapter accepts the ArrayList object in the constructor and assigns it to private List<T> mObjects;. The getCount(), getItem(), and getView() methods are implemented through mObjectmember variables.

So the adapter pattern in ListView is an object adapter pattern, not a class adapter pattern.

What problem does ArrayAdapter solve or what is its role?

Completed ArrayList<String>conversion to ListAdapter.
The source data given when using it is that ArrayList<String>ListView needs ListAdapter, and ArrayAdapter completes ArrayList<String>the conversion from ListAdapter.

Conclusion: The adapter pattern in ListView is an object adapter pattern, not a class adapter pattern.

This article: Android Design Patterns Series - Adapter Patterns analysis is pretty good, but misleading.

Guess you like

Origin blog.csdn.net/zhangjin1120/article/details/131406747