Adapter与Activity通过接口回调进行交互

0. 前言

首先说明一下为什么要写这么一篇博客:最近看了一些其他人的项目,发现很多项目的做法是建立一个专门存放Adapter类的Package包,也有的项目干脆直接都写在Activity中。而我属于后者,我并不觉得Adapter需要单独占用一个包,因为大多数时候他们并不能给其他Activity复用。

其实这两种方式都是可以的,但有一点很关键,那就是无论如何,adapter不能持有activity的引用,否则可能会因为adapter里面可能会做一些耗时操作,当activity finish时会因为被adapter持有引用而导致activity无法被回收,从而导致内存泄漏

 

1. 写在Activity外面也可能会导致内存泄漏

Java中,非静态内部类对象是会隐式持有外部类引用的,也就是说adapter持有了activity的引用。所以就有将Adapter写在单独的一个包中的做法,估计很多开发者都认为这样是为了让Activity看起来更简洁。

然而我还想说的是,adapter写在外面也阻止不了MDZZ程序员想在adapter内持有Activity引用。因为很多时候adapter不可避免的需要和Activity交互,或者需要一个context对象

 

比如说点击列表上的Item实现到跳转SecondActivity的效果,很多人可能这么做:

  1. //外面的Adapter类  
  2. public class ExampleAdapter extends BaseAdapter {  
  3.     private Context mContext;  
  4.     public ExampleAdapter(Context context) {  
  5.         this.mContext = context;  
  6.     }  
  7.   
  8.     @Override  
  9.     public View getView(int position, View convertView, ViewGroup parent) {  
  10.         if (convertView == null) {  
  11.             //这里也用到了activity的引用  
  12.             convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);  
  13.         }  
  14.         TextView textView = (TextView) convertView.findViewById(R.id.text);  
  15.         textView.setText(String.valueOf(position));  
  16.   
  17.         Button button = (Button) convertView.findViewById(R.id.button);  
  18.         button.setOnClickListener(new View.OnClickListener() {  
  19.             @Override  
  20.             public void onClick(View v) {  
  21.                 //使用构造方法传过来的上下文跳转界面  
  22.                 mContext.startActivity(new Intent(mContext, SecondActivity.class));  
  23.             }  
  24.         });  
  25.   
  26.         return convertView;  
  27. }  


  1. //MainActivity代码展示  
  2. public class MainActivity extends Activity {  
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         ListView listView = (ListView) findViewById(R.id.listView);  
  8.         //这里将activity对象传入adapter  
  9.         ExampleAdapter adapter = new ExampleAdapter(this);  
  10.         listView.setAdapter(adapter);  
  11.     }  
  12. }  

说实话,我第一次看上面代码,感觉很干净利落,甚至觉得有点舒服,==

但是这种情况下,adapter就持有了Activity引用,如果我们在adapter中进行耗时操作(比如加载图片之类的),并且finish Activity,虽然此时Activity销毁了,但是GC是无法回收activity,而且Activity占用的内存还是比较大的,这样就发生了内存泄漏。


2. 不持有Activity对象的情况下怎么和Activity交互

那么在上面的例子中,问题就集中在了如何在不持有Activity对象的情况下和Activity交互

 

2.1 首先处理getView()中的inflate()

当我们inflate一个xml时,完全可以使用parentcontext,实现如下:

 

2.2 点击事件,可以用回调接口

使用回调接口的方式来实现不持有activity的情况下,与Activity愉快的交互,实现如下:

 



3. 其实写在里面也可以呀

adapter写在Activity里面的话只需要加个static关键字(变为静态内部类)就行了,其他和写在外面是一样的。



至此关于关于ListView的Adapter应该写在Activity外面还是里面的问题就讨论结束了,其实两种方式都可以,只要留意内存泄漏的风险即可。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值