Android 开发之接口回调

很多初学者都遇到过这类问题:在列表项(ListView、GridView等)button 事件的响应与列表冲突,这一类型的问题,要解决其实很简单,且看接口回调。

在Android开发中回调用的比较广泛,主要有接口回调,类回调函数,特别类Activity直接调用方法等,这里我们先从接口回调说起,可以先来看一段简单代码块:

public class LoginImp {

    public static void main(String[] args) {
        String userName="lanyan";
        String password="12345";
        onLogin(userName, password);
    }

    public static void onLogin(String userName,String password){

    }
}

以这段代码为例,把登录方法分离到接口,用接口回调的表现形式。
形式一:


/**
 * 登录接口
 * @author LanYan
 *
 */
public interface OnLoginListener {

    /**
     * 登录方法
     * @param userName
     * @param password
     */
    void onLogin(String userName,String password);
}

修改后调用代码实例:


public class LoginImp {

    public static void main(String[] args) {
        String userName="lanyan";
        String password="12345";
        login(userName, password);
    }

    public static void login(String userName,String password){
        onLoginListener.onLogin(userName, password);
    }

    static OnLoginListener onLoginListener=new OnLoginListener() {

        @Override
        public void onLogin(String userName, String password) {

        }
    };

}

形式一的方式必须重载所有的接口定义方法,在开发中如果接口定义了多个方法,而在某块代码只需用到其中一个,此时就显得有点累赘了。具体优化稍后提到。

形式二:

public class LoginHeper {

    public void onLogin(String userName,String password){

    }

    public void onLogout(String userName,String password){

    }
}

形式二的代码调用实例:


public class LoginImp {

    public static void main(String[] args) {
        String userName="lanyan";
        String password="12345";
        login(userName, password);
    }

    public static void login(String userName,String password){
        mLoginHelper.onLogin(userName, password);
    }

    static LoginHeper mLoginHelper=new LoginHeper(){
        public void onLogin(String userName, String password) {

        }
    };

}

看似代码相差不大,但是仔细的同学就会发现,LoginHeler内部有两个方法,这里只选择重载了onLogin方法,这是一大亮点,但是当用户不想手动重载时,缺点就出来了。不过可以考虑配合结合接口使用,达到鬼斧神工之效。具体详解往下看

形式三:

public class LoginImp implements OnLoginListener{

    public static void main(String[] args) {
        String userName="lanyan";
        String password="12345";

        login(userName, password,new LoginImp(){
            @Override
            public void onLogin(String userName, String password) {
                // TODO Auto-generated method stub
                super.onLogin(userName, password);
            }
        });
    }

    public static void login(String userName,String password,LoginImp mCallback){
        mCallback.onLogin(userName, password);
    }

    @Override
    public void onLogin(String userName, String password) {

    }
}

表现形式三通过类实现接口,调用时通过类实例调用方法,与形式一差别不大,但在某种情况下,不希望手动重载,这样就显得不够完美了。

表现形式四:

public interface OnProgressListener {

    void onStart();

    void onProgress(int progress,int currentSize,int totalSize);

    void onStop();
}

public abstract class OnHttpListener implements OnProgressListener{

    @Override
    public void onStart() {
        // TODO Auto-generated method stub

    }

    @Override
    public void onProgress(int progress, int currentSize, int totalSize) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onStop() {
        // TODO Auto-generated method stub

    }

    public abstract void onFail(Exception e,String result);
    public abstract void onSuccess(String result);

}

测试代码:


public class HttpTest {

    public static void main(String[] args) {
        new HttpTest().doPost(null, null, new OnHttpListener() {

            public void onStart() {
                //手动重载
            }

            @Override
            public void onSuccess(String result) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onFail(Exception e, String result) {
                // TODO Auto-generated method stub

            }
        } );
    }
    public void doPost(String url,JSONObject requestJson,OnHttpListener onHttpListener){

    }
}

表现形式四是最好用的也是用的最广泛的,比如Xutils框架等第三方框架有用到。

表现形式五:

public abstract class OnProgressListener {

    protected abstract void onStart();

    protected abstract void onProgress(int progress,int currentSize,int totalSize);

    protected abstract void onStop();
}
public abstract class OnHttpListener extends OnProgressListener{

    @Override
    protected void onStart() {
        // TODO Auto-generated method stub

    }

    @Override
    protected void onProgress(int progress, int currentSize, int totalSize) {
        // TODO Auto-generated method stub

    }

    @Override
    protected void onStop() {
        // TODO Auto-generated method stub

    }

    public abstract void onFail(Exception e,String result);
    public abstract void onSuccess(String result);

}

形式五,这里把接口改用抽象,把实现改用继承,相比较形式四哪一种更好,这里暂不讨论。,先通过一段Activity配合adapter的调用实例,让我们深入理解接口回调:

定义列表的相关接口:

import android.view.View;

public interface ListListener{

    interface OnCheckedListener{

        void onCheckedChange(boolean isChecked ,int position);
    }

    interface OnClickListener<T>{

        void onClick(View v, T result ,int position);
    }

    void onReferesh();

    void onBackTop();

    void onScrollTop(int distance);

    void onScrollBottom(int distance);
}

接口的抽象实现类:


public abstract class OnListListener<T> implements ListListener,OnCheckedListener,OnClickListener<T>{

    @Override
    public void onCheckedChange(boolean isChecked, int position) {

    }

    @Override
    public void onClick(View v, T result, int position) {

    }

    @Override
    public void onBackTop() {

    }

    @Override
    public void onReferesh() {

    }

    @Override
    public void onScrollBottom(int distance) {

    }

    @Override
    public void onScrollTop(int distance) {

    }

    public abstract void onItemClick(View v,T result ,int position);

}

adapter基类(部分空方法具体实现这里就不写了,这不是重点哇)


import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;

import com.example.interfaces.OnListListener;

public abstract class ListAdapter<T> extends BaseAdapter{

    protected LayoutInflater mInflater;
    protected ArrayList<T> mList;
    protected Context mContext;
    protected OnListListener<T> callback=null;

    public ListAdapter(Context mContext,ArrayList<T> mList) {
        this(mContext, mList, null);
    }

    public ListAdapter(Context mContext,ArrayList<T> mList,OnListListener<T> callback) {
        initiazed(mContext, mList, callback);

    }

    public void initiazed(Context mContext,ArrayList<T> mList,OnListListener<T> callback){
        this.mContext=mContext;
        this.mInflater=LayoutInflater.from(mContext);
        setmList(mList);
        this.callback=callback;
    }

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

    @Override
    public T getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position,View convertView,final ViewGroup parent) {

        if(convertView==null){
            convertView=mInflater.inflate(setContextView(), null);
        }

        convertView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                if(callback!=null){
                    //OnItemClick回调,从此不再调用系统的OnItemClickListener了
                    callback.onItemClick(parent, getItem(position), position);
                }
            }
        });

        initView(convertView,getItem(position),position);
        return convertView;
    }
    public ArrayList<T> getmList() {
        return mList;
    }
    public void setmList(ArrayList<T> mList) {
        if(mList==null){
            this.mList=new ArrayList<T>();
        }else{
            this.mList = mList;
        }
    }

    public void setOnListListener(OnListListener<T> callback){

        this.callback=callback;
    }

    public OnListListener<T> getOnListListener(){

        return callback;
    }

    public void onReferesh(ArrayList<T> mList){

    }

    public void onLoadMore(ArrayList<T> mList){

    }

    public void removeItem(int position){

    }

    public void removeCollection(ArrayList<T> mList){

    }

    public void updateItem(T result){

    }

    public abstract int setContextView();

    public abstract void initView(View converView,T result,int position);

}

adapter测试类OptionAdapter:


public class OptionAdapter extends ListAdapter<UserBean>{

    //两个构造方法可根据自己习惯调用
    public OptionAdapter(Context mContext, ArrayList<UserBean> mList,
            OnListListener<UserBean> callback) {
        super(mContext, mList, callback);
    }

    public OptionAdapter(Context mContext, ArrayList<UserBean> mList) {
        this(mContext, mList,null);
    }

    @Override
    public int setContextView() {
        return R.layout.item_option;
    }

    @Override
    public void initView(final View converView,final UserBean result,final int position) {
        //这里面给控件赋值,并对空间给予监听,回调相关方法,方法不足时自行扩展,这里可通过辅助类
        //ViewHoler.get()..辅助完成赋值,

    }

}

下面是Activity调用实例:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //方法一
        adapter=new OptionAdapter(this, null);
        mListView.setAdapter(adapter);
        adapter.setOnListListener(new OnListListener<UserBean>() {

            @Override
            public void onItemClick(View v, UserBean result, int position) {

            }

            @Override
            public void onCheckedChange(boolean isChecked, int position) {
                super.onCheckedChange(isChecked, position);
                //手动可选重载方法
            }

        });
      //方法二
      adapter=new OptionAdapter(this, null,new OnListListener<UserBean>() {

            @Override
            public void onItemClick(View v, UserBean result, int position) {
                // TODO Auto-generated method stub

            }
        });
    }

下面我们来浅谈接口回调在Volley框架的具体实战。

Volley里的重定向接口定义:

public abstract interface RetryPolicy
{
  public abstract int getCurrentTimeout();

  public abstract int getCurrentRetryCount();

  public abstract void retry(VolleyError paramVolleyError)
    throws VolleyError;
}

该接口的实现类如下(这种接口定义,把参数分离出接口,又其实现类构造方法传入参数,这是一大亮点):

public class DefaultRetryPolicy implements RetryPolicy{
 //.................此处略.......................
  public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier){
    this.mCurrentTimeoutMs = initialTimeoutMs;
    this.mMaxNumRetries = maxNumRetries;
    this.mBackoffMultiplier = backoffMultiplier;
  }

  public int getCurrentTimeout(){
    return this.mCurrentTimeoutMs;
  }

  public int getCurrentRetryCount(){
    return this.mCurrentRetryCount;
  }
}

Volley里的cache缓存接口定义如下:

import java.util.Collections;
import java.util.Map;

public abstract interface Cache
{
  public abstract Entry get(String paramString);

  public abstract void put(String paramString, Entry paramEntry);

  public abstract void initialize();

  public abstract void invalidate(String paramString, boolean paramBoolean);

  public abstract void remove(String paramString);

  public abstract void clear();

  public static class Entry
  {
    public byte[] data;
    public String etag;
    public long serverDate;
    public long ttl;
    public long softTtl;
    public Map<String, String> responseHeaders = Collections.emptyMap();

    public boolean isExpired()
    {
      return this.ttl < System.currentTimeMillis();
    }

    public boolean refreshNeeded()
    {
      return this.softTtl < System.currentTimeMillis();
    }
  }
}

缓存的实现类(重载interface接口的方法并添加了同步关键字):

public class DiskBasedCache implements Cache{
 //..........此处略.......
  public DiskBasedCache(File rootDirectory, int maxCacheSizeInBytes)
  {
    this.mRootDirectory = rootDirectory;
    this.mMaxCacheSizeInBytes = maxCacheSizeInBytes;
  }

  public DiskBasedCache(File rootDirectory)
  {
    this(rootDirectory, 5242880);
  }

  public synchronized void clear()
  {
    File[] files = this.mRootDirectory.listFiles();
    if (files != null) {
      for (File file : files) {
        file.delete();
      }
    }
    this.mEntries.clear();
    this.mTotalSize = 0L;
    VolleyLog.d("Cache cleared.", new Object[0]);
  }

  public synchronized Cache.Entry get(String key)
  {
    //..........此处略.......
  }
}

诸如此类的接口回调着实太多,就不一一列举了,顺便提一下,当下各种框架盛行,让开发者不知道该如何选择是好,其实原理都大同小异差别不大,10分钟左右就可以上手,我们应该至少应该精通一种框架开发,提高开发效率,至于其他的额框架还是应该有个了解(换到不同的公司后可以一眼就认出使用框架,以免被人认为是小白,嘿嘿)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值