告诉你ListView的Adapter应该写在Activity外面还是里面

一、Adapter写在哪并不是重点

ListView的Adapter应该写在Activity外面还是里面?
我想很多很多开发者估计都不知道这个问题。
而有部分人可能会嗤之以鼻,adapter写在外面和里面不都一样么?爱怎么写怎么写

这话没错,其实写在哪里都是没有问题的。

请别拍我板砖,我不是来搞笑的。

我先要说明一下我为什么要写这么一篇博客。
最近看了一些其他同时以前的项目,发现大多数项目的做法是建立一个package包专门存放Adapter类的,也有的人会嫌麻烦两个类切来切去,干脆都写在Activity中。
而我属于后者,我并不觉得adapter需要单独占用一个包,因为大多数时候他们并不能给其他Activity复用。

然而这两种方式都是可以的,看个人习惯或者团队做法了。
但有一点很关键,无论如何,adapter不能持有activity的引用!否则会出现内存泄漏的风险!
为什么呢? 因为adapter里面可能会做一些耗时操作,当finish activity时会因为被adapter持有引用而导致activity无法被回收,从而导致内存泄漏。

二、Adapter为什么写在Activity外面

上面也说了,adapter不能持有Activity的引用,否则会有内存泄漏的风险。
而Java中,非静态内部类对象是会隐式持有外部类引用的,也就是说adapter持有了activity的引用……
关于内部类可以看这篇博客:Java中的内部类和匿名类

所以就有将Adapter写在单独的一个包中的做法,估计很多开发者都不知道原来是这个原因,认为只是为了让Activity看起来更简洁。

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

比如说这种情况……

需要点击某个Item中的Button,跳转到一个新的Activity的时候。
很多人会这么做……

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.listView);
        // 看这里,activity对象传入adapter
        ExampleAdapter adapter = new ExampleAdapter(this);
        listView.setAdapter(adapter);
    }
}
public class ExampleAdapter extends BaseAdapter {

    // 看这里,持有了Activity引用
    private Context mContext;
    public ExampleAdapter(Context context) {
        this.mContext = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
        // 这里也用到了activity的引用……
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
        }
        TextView textView = (TextView) convertView.findViewById(R.id.text);
        textView.setText(String.valueOf(position));

        Button button = (Button) convertView.findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 看这里,跳转activity……
                mContext.startActivity(new Intent(mContext, SecondActivity.class));
            }
        });

        return convertView;
    }

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

三、不持有Activity对象的情况下怎么和Activity交互

首先说明一种情况,有人会想着使用弱引用来保存Activity。
但我认为这是不好的做法,因为弱引用对象随时都有可能被回收,虽然可以判断是否为空不至于报空指针异常,但是会导致和Activity交互失败。用户体验肯定是不好的

在上main的例子中,想要和Activity交互还是有很多方式的。
首先我们来说一下inflate一个xml,完全可以使用parent的context,如下

然后button的点击跳转Activity,我们可以弄一个回调,如:
adapter构造中的context忘记删除了,别在意细节……反正没持有引用

这里写图片描述
这样就可以在不持有activity的情况下愉快的交互了

四、说好的Adapter写在内部呢

别急,adapter写在Activity里面的话只需要加个static关键字就行了,其他和写在外面是一样的。

结语:
Adapter到底写在哪呢?
你怎么舒服怎么来就行了,千万小心不要导致内存泄漏就行,反正我是喜欢写里边,隐藏外部访问并且写起来舒服╮(╯-╰)╭

不止adapter,如果还写了的话也要写成静态的内部类哦
还有handler之类的~~~

转自:Altsuki的博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值