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

来源:互联网 发布:mac word 用户权限 编辑:程序博客网 时间:2024/05/22 06:21

一、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之类的~~~









最近都是上班敲代码,下班后也宿舍敲到12点,忙里偷闲写了这篇博客,感觉整个人都被掏空了啊啊啊啊啊啊啊啊啊啊。
今晚我决定要玩游戏!不敲代码了,我这是保护头发,小心中年谢顶这里写图片描述

2 0
原创粉丝点击