ym——Android之Adapter优化

来源:互联网 发布:数据泄漏防护系统 破解 编辑:程序博客网 时间:2024/04/29 03:10

转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持!


做过Android开发的都知道,Adapter的使用频率很高。无论是ListView、GridView、Gallery都需要设置Adapter,而且它们的Adapter几乎一样,让我们来看看我们经常用到的Adapter吧,我们可以边看边思考到底有多少东西是我们经常需要重复的:

先从构造说起:LayoutInflater重复

public MyAdapter1(Context context, int resId, List<String> data) {mData = data;mContext = context;mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);mLayoutResId = resId;}
在说说其他需要重写的方法:以下3个方法都是重复的写(无任何技术含量)

@Overridepublic int getCount() {return mData.size();}@Overridepublic Object getItem(int arg0) {return mData.get(arg0);}@Overridepublic long getItemId(int arg0) {return arg0;}

在看看最重要的getView方法:无非就是重用View,setTag (ViewHolder),除了ViewHolder的get和set内容不一样其他都是在重复(伤不起有木有~!)。
public View getView(int position, View view, ViewGroup viewgroup) {if (view == null) {mHolder = new ViewHolder();view = mInflater.inflate(mLayoutResId, null);mHolder.tvText = (TextView) view.findViewById(android.R.id.text1);view.setTag(mHolder);} else {mHolder = (ViewHolder) view.getTag();}mHolder.tvText.setText(mData.get(position).toString());return view;}static class ViewHolder {TextView tvText;}
我们完全可以写两个基类把重复的东西抽取出来把代码优化一下,看一下优化后的代码吧:(在git看到的)
package com.cym.chadtestdemo;import java.util.List;import android.content.Context;import android.view.View;import android.view.ViewGroup;import com.chronocloud.lib.base.BaseAdapterHelper;import com.chronocloud.lib.base.BaseQuickAdapter;/** *  * @ClassName: MyAdapter * @Description: TODO 简化后的Adapter * @author Chad.Cym * @date 2014年8月25日 下午8:22:31 *  * @param <T> */public class MyAdapter<T> extends BaseQuickAdapter<T, BaseAdapterHelper> {public MyAdapter(Context context, int layoutResId, List<T> data) {super(context, layoutResId, data);}@Overrideprotected void convert(BaseAdapterHelper helper, T item) {helper.setText(android.R.id.text1, item.toString());}@Overrideprotected BaseAdapterHelper getAdapterHelper(int position,View convertView, ViewGroup parent) {return BaseAdapterHelper.get(context, convertView, parent, layoutResId);}}
优化后只需要设置控件内容即可,不需要重复之前的所有重复代码了。我们来看看抽取出来的基类:
package com.chronocloud.lib.base;/** * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.ImageLoader;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Paint;import android.graphics.Typeface;import android.graphics.drawable.Drawable;import android.os.Build;import android.text.util.Linkify;import android.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.animation.AlphaAnimation;import android.widget.Adapter;import android.widget.AdapterView;import android.widget.Checkable;import android.widget.CompoundButton;import android.widget.ImageView;import android.widget.ProgressBar;import android.widget.RatingBar;import android.widget.TextView;/** * Allows an abstraction of the ViewHolder pattern.<br> * <br> * <p/> * <b>Usage</b> * <p/> *  * <pre> * return BaseAdapterHelper.get(context, convertView, parent, R.layout.item) * .setText(R.id.tvName, contact.getName()) * .setText(R.id.tvEmails, contact.getEmails().toString()) * .setText(R.id.tvNumbers, contact.getNumbers().toString()).getView(); * </pre> */public class BaseAdapterHelper {/** Views indexed with their IDs */private final SparseArray<View> views;private final Context context;private int position;private View convertView;/** * Package private field to retain the associated user object and detect a * change */Object associatedObject;private BaseAdapterHelper(Context context, ViewGroup parent, int layoutId,int position) {this.context = context;this.position = position;this.views = new SparseArray<View>();convertView = LayoutInflater.from(context) //.inflate(layoutId, parent, false);convertView.setTag(this);}/** * This method is the only entry point to get a BaseAdapterHelper. *  * @param context *            The current context. * @param convertView *            The convertView arg passed to the getView() method. * @param parent *            The parent arg passed to the getView() method. * @return A BaseAdapterHelper instance. */public static BaseAdapterHelper get(Context context, View convertView,ViewGroup parent, int layoutId) {return get(context, convertView, parent, layoutId, -1);}/** This method is package private and should only be used by QuickAdapter. */static BaseAdapterHelper get(Context context, View convertView,ViewGroup parent, int layoutId, int position) {if (convertView == null) {return new BaseAdapterHelper(context, parent, layoutId, position);}// Retrieve the existing helper and update its positionBaseAdapterHelper existingHelper = (BaseAdapterHelper) convertView.getTag();existingHelper.position = position;return existingHelper;}/** * This method allows you to retrieve a view and perform custom operations * on it, not covered by the BaseAdapterHelper.<br/> * If you think it's a common use case, please consider creating a new issue * at https://github.com/JoanZapata/base-adapter-helper/issues. *  * @param viewId *            The id of the view you want to retrieve. */public <T extends View> T getView(int viewId) {return retrieveView(viewId);}/** * Will set the text of a TextView. *  * @param viewId *            The view id. * @param value *            The text to put in the text view. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setText(int viewId, String value) {TextView view = retrieveView(viewId);view.setText(value);return this;}/** * Will set the image of an ImageView from a resource id. *  * @param viewId *            The view id. * @param imageResId *            The image resource id. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setImageResource(int viewId, int imageResId) {ImageView view = retrieveView(viewId);view.setImageResource(imageResId);return this;}/** * Will set background color of a view. *  * @param viewId *            The view id. * @param color *            A color, not a resource id. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setBackgroundColor(int viewId, int color) {View view = retrieveView(viewId);view.setBackgroundColor(color);return this;}/** * Will set background of a view. *  * @param viewId *            The view id. * @param backgroundRes *            A resource to use as a background. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setBackgroundRes(int viewId, int backgroundRes) {View view = retrieveView(viewId);view.setBackgroundResource(backgroundRes);return this;}/** * Will set text color of a TextView. *  * @param viewId *            The view id. * @param textColor *            The text color (not a resource id). * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setTextColor(int viewId, int textColor) {TextView view = retrieveView(viewId);view.setTextColor(textColor);return this;}/** * Will set text color of a TextView. *  * @param viewId *            The view id. * @param textColorRes *            The text color resource id. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setTextColorRes(int viewId, int textColorRes) {TextView view = retrieveView(viewId);view.setTextColor(context.getResources().getColor(textColorRes));return this;}/** * Will set the image of an ImageView from a drawable. *  * @param viewId *            The view id. * @param drawable *            The image drawable. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setImageDrawable(int viewId, Drawable drawable) {ImageView view = retrieveView(viewId);view.setImageDrawable(drawable);return this;}/** * Will download an image from a URL and put it in an ImageView.<br/> * It uses Square's Picasso library to download the image asynchronously and * put the result into the ImageView.<br/> * Picasso manages recycling of views in a ListView.<br/> * If you need more control over the Picasso settings, use * {BaseAdapterHelper#setImageBuilder}. *  * @param viewId *            The view id. * @param imageUrl *            The image URL. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setImageUrl(int viewId, String imageUrl) {ImageView view = retrieveView(viewId);ImageLoader.getInstance().displayImage(imageUrl, view);return this;}public BaseAdapterHelper setImageUrl(int viewId, String imageUrl,DisplayImageOptions options) {ImageView view = retrieveView(viewId);ImageLoader.getInstance().displayImage(imageUrl, view, options);return this;}/** * Add an action to set the image of an image view. Can be called multiple * times. */public BaseAdapterHelper setImageBitmap(int viewId, Bitmap bitmap) {ImageView view = retrieveView(viewId);view.setImageBitmap(bitmap);return this;}/** * Add an action to set the alpha of a view. Can be called multiple times. * Alpha between 0-1. */public BaseAdapterHelper setAlpha(int viewId, float value) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {retrieveView(viewId).setAlpha(value);} else {// Pre-honeycomb hack to set Alpha valueAlphaAnimation alpha = new AlphaAnimation(value, value);alpha.setDuration(0);alpha.setFillAfter(true);retrieveView(viewId).startAnimation(alpha);}return this;}/** * Set a view visibility to VISIBLE (true) or GONE (false). *  * @param viewId *            The view id. * @param visible *            True for VISIBLE, false for GONE. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setVisible(int viewId, boolean visible) {View view = retrieveView(viewId);view.setVisibility(visible ? View.VISIBLE : View.GONE);return this;}/** * Add links into a TextView. *  * @param viewId *            The id of the TextView to linkify. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper linkify(int viewId) {TextView view = retrieveView(viewId);Linkify.addLinks(view, Linkify.ALL);return this;}/** Apply the typeface to the given viewId, and enable subpixel rendering. */public BaseAdapterHelper setTypeface(int viewId, Typeface typeface) {TextView view = retrieveView(viewId);view.setTypeface(typeface);view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);return this;}/** * Apply the typeface to all the given viewIds, and enable subpixel * rendering. */public BaseAdapterHelper setTypeface(Typeface typeface, int... viewIds) {for (int viewId : viewIds) {TextView view = retrieveView(viewId);view.setTypeface(typeface);view.setPaintFlags(view.getPaintFlags() | Paint.SUBPIXEL_TEXT_FLAG);}return this;}/** * Sets the progress of a ProgressBar. *  * @param viewId *            The view id. * @param progress *            The progress. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setProgress(int viewId, int progress) {ProgressBar view = retrieveView(viewId);view.setProgress(progress);return this;}/** * Sets the progress and max of a ProgressBar. *  * @param viewId *            The view id. * @param progress *            The progress. * @param max *            The max value of a ProgressBar. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setProgress(int viewId, int progress, int max) {ProgressBar view = retrieveView(viewId);view.setMax(max);view.setProgress(progress);return this;}/** * Sets the range of a ProgressBar to 0...max. *  * @param viewId *            The view id. * @param max *            The max value of a ProgressBar. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setMax(int viewId, int max) {ProgressBar view = retrieveView(viewId);view.setMax(max);return this;}/** * Sets the rating (the number of stars filled) of a RatingBar. *  * @param viewId *            The view id. * @param rating *            The rating. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setRating(int viewId, float rating) {RatingBar view = retrieveView(viewId);view.setRating(rating);return this;}/** * Sets the rating (the number of stars filled) and max of a RatingBar. *  * @param viewId *            The view id. * @param rating *            The rating. * @param max *            The range of the RatingBar to 0...max. * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setRating(int viewId, float rating, int max) {RatingBar view = retrieveView(viewId);view.setMax(max);view.setRating(rating);return this;}/** * Sets the on click listener of the view. *  * @param viewId *            The view id. * @param listener *            The on click listener; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setOnClickListener(int viewId,View.OnClickListener listener) {View view = retrieveView(viewId);view.setOnClickListener(listener);return this;}/** * Sets the on touch listener of the view. *  * @param viewId *            The view id. * @param listener *            The on touch listener; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setOnTouchListener(int viewId,View.OnTouchListener listener) {View view = retrieveView(viewId);view.setOnTouchListener(listener);return this;}/** * Sets the on long click listener of the view. *  * @param viewId *            The view id. * @param listener *            The on long click listener; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setOnLongClickListener(int viewId,View.OnLongClickListener listener) {View view = retrieveView(viewId);view.setOnLongClickListener(listener);return this;}/** * Sets the tag of the view. *  * @param viewId *            The view id. * @param tag *            The tag; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setTag(int viewId, Object tag) {View view = retrieveView(viewId);view.setTag(tag);return this;}/** * Sets the tag of the view. *  * @param viewId *            The view id. * @param key *            The key of tag; * @param tag *            The tag; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setTag(int viewId, int key, Object tag) {View view = retrieveView(viewId);view.setTag(key, tag);return this;}/** * Sets the checked status of a checkable. *  * @param viewId *            The view id. * @param checked *            The checked status; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setChecked(int viewId, boolean checked) {Checkable view = (Checkable) retrieveView(viewId);view.setChecked(checked);return this;}/** * Sets the adapter of a adapter view. *  * @param viewId *            The view id. * @param adapter *            The adapter; * @return The BaseAdapterHelper for chaining. */public BaseAdapterHelper setAdapter(int viewId, Adapter adapter) {AdapterView view = retrieveView(viewId);view.setAdapter(adapter);return this;}/** Retrieve the convertView */public View getView() {return convertView;}/** * Retrieve the overall position of the data in the list. *  * @throws IllegalArgumentException *             If the position hasn't been set at the construction of the *             this helper. */public int getPosition() {if (position == -1)throw new IllegalStateException("Use BaseAdapterHelper constructor "+ "with position if you need to retrieve the position.");return position;}@SuppressWarnings("unchecked")private <T extends View> T retrieveView(int viewId) {View view = views.get(viewId);if (view == null) {view = convertView.findViewById(viewId);views.put(viewId, view);}return (T) view;}}

package com.chronocloud.lib.base;/** * Copyright 2013 Joan Zapata * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import android.content.Context;import android.view.Gravity;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.FrameLayout;import android.widget.ProgressBar;import java.util.ArrayList;import java.util.List;/** * Abstraction class of a BaseAdapter in which you only need * to provide the convert() implementation.<br/> * Using the provided BaseAdapterHelper, your code is minimalist. * @param <T> The type of the items in the list. */public abstract class BaseQuickAdapter<T, H extends BaseAdapterHelper> extends BaseAdapter {protected static final String TAG = BaseQuickAdapter.class.getSimpleName();    protected final Context context;protected final int layoutResId;protected final List<T> data;protected boolean displayIndeterminateProgress = false;    /**     * Create a QuickAdapter.     * @param context     The context.     * @param layoutResId The layout resource id of each item.     */    public BaseQuickAdapter(Context context, int layoutResId) {        this(context, layoutResId, null);    }    /**     * Same as QuickAdapter#QuickAdapter(Context,int) but with     * some initialization data.     * @param context     The context.     * @param layoutResId The layout resource id of each item.     * @param data        A new list is created out of this one to avoid mutable list     */    public BaseQuickAdapter(Context context, int layoutResId, List<T> data) {        this.data = data == null ? new ArrayList<T>() : new ArrayList<T>(data);        this.context = context;        this.layoutResId = layoutResId;    }    @Override    public int getCount() {        int extra = displayIndeterminateProgress ? 1 : 0;        return data.size() + extra;    }    @Override    public T getItem(int position) {        if (position >= data.size()) return null;        return data.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public int getViewTypeCount() {        return 2;    }    @Override    public int getItemViewType(int position) {        return position >= data.size() ? 1 : 0;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        if (getItemViewType(position) == 0) {            final H helper = getAdapterHelper(position, convertView, parent);            convert(helper, getItem(position));            return helper.getView();        }        return createIndeterminateProgressView(convertView, parent);    }    private View createIndeterminateProgressView(View convertView, ViewGroup parent) {        if (convertView == null) {            FrameLayout container = new FrameLayout(context);            container.setForegroundGravity(Gravity.CENTER);            ProgressBar progress = new ProgressBar(context);            container.addView(progress);            convertView = container;        }        return convertView;    }    @Override    public boolean isEnabled(int position) {        return position < data.size();    }    public void add(T elem) {        data.add(elem);        notifyDataSetChanged();    }    public void addAll(List<T> elem) {        data.addAll(elem);        notifyDataSetChanged();    }    public void set(T oldElem, T newElem) {    set(data.indexOf(oldElem), newElem);    }    public void set(int index, T elem) {        data.set(index, elem);        notifyDataSetChanged();    }    public void remove(T elem) {    data.remove(elem);    notifyDataSetChanged();    }    public void remove(int index) {        data.remove(index);        notifyDataSetChanged();    }    public void replaceAll(List<T> elem) {        data.clear();        data.addAll(elem);        notifyDataSetChanged();    }    public boolean contains(T elem) {        return data.contains(elem);    }    /** Clear data list */    public void clear() {        data.clear();        notifyDataSetChanged();    }    public void showIndeterminateProgress(boolean display) {        if (display == displayIndeterminateProgress) return;        displayIndeterminateProgress = display;        notifyDataSetChanged();    }    /**     * Implement this method and use the helper to adapt the view to the given item.     * @param helper A fully initialized helper.     * @param item   The item that needs to be displayed.     */    protected abstract void convert(H helper, T item);/** * You can override this method to use a custom BaseAdapterHelper in order to fit your needs * * @param position The position of the item within the adapter's data set of the item whose view we want. * @param convertView The old view to reuse, if possible. Note: You should check that this view *        is non-null and of an appropriate type before using. If it is not possible to convert *        this view to display the correct data, this method can create a new view. *        Heterogeneous lists can specify their number of view types, so that this View is *        always of the right type (see {@link #getViewTypeCount()} and *        {@link #getItemViewType(int)}). * @param parent The parent that this view will eventually be attached to * @return An instance of BaseAdapterHelper */protected abstract H getAdapterHelper(int position, View convertView, ViewGroup parent);}
效果很明显,简单多了吧,希望能对大家有帮助。
源码地址:https://github.com/JoanZapata/base-adapter-helper 

6 0
原创粉丝点击