Posts Tagged ‘Android’

ViewPager 的点击监听与存在的误触问题

in 在路上

ViewPager 是不自带 onItemClickListener 之类的方法的,解决方案也很简单,就是在 PagerAdapter 的 instantiateItem 方法里为每个页面加上监听。这是业界通常的做法,但是为毛没一个人提到这样会产生误触问题呢Orz……虽然解决误触也不复杂啦,但是我还是纳闷为啥我之前搜都没有相关资料呢……所以我还是写下这篇帮助下会被此困扰的人吧。

ViewPager 的点击事件监听

public class StartViewPagerAdapter extends PagerAdapter {
    private List mListViews;
    private View.OnClickListener clickListener;

    public StartViewPagerAdapter(List mListViews,View.OnClickListener clickListener) {
        this.mListViews = mListViews;
        this.clickListener=clickListener;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {  
        container.addView(mListViews.get(position), 0);
        mListViews.get(position).setOnClickListener(clickListener);
        //TODO 后面解决误触的代码
        return mListViews.get(position);
    }
}

然后创建的时候把 clickListener 传进来就行,没啥好说的。
(更多…)

Android序列化中由于修改类的内容造成InvalidClassException的解决方案

in 在路上

好多年没写博文了,我果然没救了。不过这篇文章定义应该是符合并不是互联网里满大街的知识点的要求吧。

问题回顾

在我的Exlink2.0版本升级到2.1中,之前保存的规则信息全部被清空了,而我的规则信息是通过对象序列化存储的。经初步排查,报错信息为

java.io.InvalidClassException: com.xloger.exlink.app.b.c; Incompatible class (SUID): com.xloger.exlink.app.b.c: static final long serialVersionUID =86222585354990243L; but expected com.xloger.exlink.app.b.c: static final long serialVersionUID =-4642583507468338732L;

解决这个报错的方案网上有很多,但是尝试后并没有解决我的问题,因此写下这篇博文。

序列化与serialVersionUID

序列化就是将一个对象转换为一个字节序列(目的是能存储和传输对象)。而上面的InvalidClassException恰好就是在反序列化(将一个字节序列转换回一个对象)时会产生的。

而这个InvalidClassException的原因是这样的:在一个对象(比如继承自Rule类)与字节序列的相互转换中,必然需要一个标记来证明它是Rule类的对象,否则谁知道你是Rule类还是String类还是什么,那没法反序列化了。因此,Java规定了一个属性serialVersionUID来区分它们,这个属性是可以在你需要序列化的类里申明的,比如这样:

private static final long serialVersionUID=10086L;

设定为private是为了不被子类继承。当然了,大部分人会说我以前没写过serialVersionUID啊,都是继承了Serializable接口就没了啊,是的,当没有申明serialVersionUID的时候,JVM会自动地根据包名、类名、继承关系、非私有的方法和属性,以及参数、返回值等诸多因子计算出一个值。比如我的Exlink在2.0版本之前,它给我计算的这个值为86222585354990243L,而在2.1版本中我对Rule类做了一些修改,导致该serialVersionUID变成了-4642583507468338732L。因此虽然我做的改动并不会真的影响到反序列化,但是JVM依旧会认为这有问题,因此抛出了InvalidClassException。

Ok,解决方案很简单,为了兼容以前的版本,我仅仅需要在Rule类里把serialVersionUID定义为86222585354990243L,这样JVM在反序列化的时候依旧会把最新版的Rule和旧的Rule当成一个来处理了。

也许有人会纳闷一些兼容性的问题,首先分成向上兼容、向下兼容两种。假如我们的新版增加了一个属性比如age,向上兼容就是旧的客户端读取新的数据,这里JVM会自动把那些它不认识的数据忽略掉(比如age),所以只要不改动旧属性,不用担心向上兼容的问题。向下兼容是新的客户端读取旧的数据,对于新的属性都会为Java里该类型的默认值,比如null、0、false这些。哪怕你定义你的成员变量private int age=12,这里的值依旧是0。那想做向下兼容应该怎么处理呢,就是在读取数据之后进行检测,判断是旧版本后手动初始化,比如可以维护一个当前类的版本的变量来判断。或者Android可以直接读取程序的versionCode来作为判断变量。

(更多…)

© 2018 一隅 - Powered by Wordpress / Theme: Tabinikki