从ArrayList<Long>通过Intent传递的稳妥方法

16
我当前正在编写一个应用程序,通过json从服务器获取长整型数组,然后将该列表从一个活动传递到另一个活动。 基本框架如下:
public void onResponse(Map result)
{
    ArrayList handles= (ArrayList)result.get("fileHandles");

    Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
    intent.putExtra("handles", handles);
}

因此,第一个问题变得明显起来,即 putExtra 方法的唯一方法是 putIntegerArrayListExtraputStringArrayListExtraputCharSequenceArrayListExtraputParcelableArrayListExtra。我认为 Long 可能会是 parcelable,但我错了,它不起作用(即使我使用 ArrayList<Long>)。接下来,我想只是传递一个 long [],但我发现没有直接的转换方法可以将 ArrayList<Long> 转换成 intent.putExtra 将接受的 long []。这就是我最终采取的解决方案:

ArrayList handles= (ArrayList)result.get("fileHandles");
long [] handleArray = new long[handles.size()];
for (int i = 0; i < handles.size(); i++)
{
    handleArray[i] = Long.parseLong(handles.get(i).toString());
}

显然,这对我来说有点荒谬,但我尝试了其他每一种转换方式都因为某种原因而出现问题。 我考虑重新思考我的序列化方式,在到达这一点之前先解决问题,但我觉得通过从活动传递 ArrayList<Long> 可以如此困难,这很奇怪。 我是否错过了更明显的解决方案?

顺便提一下:当源是 ArrayList<Long> 时,Long.parseLong(handles.get(i).toString()); 可以写成 (long)(Long)handles.get(i)(在上下文中,(long) 实际上是可选的)。它使用了一个向下转型,然后是一个显式(或隐式)的取消自动装箱,而不是 Long->String->long。 - user2864740
问题在于,如果handles.get(i)返回的是小于20亿左右的整数,则会导致无效转换。 - Kevin DiTraglia
2个回答

21

您可以将它用作Serializable附加项。ArrayListSerializable的,而Long扩展了实现SerializableNumber

// Put as Serializable
i.putExtra("handles", handles);

// Unfortunately you'll get an unsafe cast warning here, but it's safe to use
ArrayList<Long> handles = (ArrayList<Long>) i.getSerializableExtra("handles");    

我在Intent上没有看到putSerializable作为一个选项。 - Kevin DiTraglia
抱歉,我看错了,我是在看 Bundle 而不是 Intent。请看编辑后的内容。 :) - Kevin Coppock
明白了,简单多了,非常感谢。删除刚刚写的那些可怕的代码感觉很好。 - Kevin DiTraglia
它的内存使用效率并不是很高。请参考:http://www.developerphil.com/parcelable-vs-serializable/ - Egemen Hamutçu

3

两个选项:使用 Parcelable 或者 Serializable

介绍:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("handles", new FileHandles(handles));

输出:

FileHandles handles = intent.getParcelableExtra("handles");

对象:

import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;

public class FileHandles implements Parcelable {

    private final List<Long> fileHandles;

    public FileHandles(List<Long> fileHandles) {
        this.fileHandles = fileHandles;
    }

    public FileHandles(Parcel in) {
        int size = in.readInt();
        long[] parcelFileHandles = new long[size];
        in.readLongArray(parcelFileHandles);
        this.fileHandles = toObjects(size, parcelFileHandles);
    }

    private List<Long> toObjects(int size, long[] parcelFileHandles) {
        List<Long> primitiveConv = new ArrayList<Long>();
        for (int i = 0; i < size; i++) {
            primitiveConv.add(parcelFileHandles[i]);
        }
        return primitiveConv;
    }

    public List<Long> asList() { // Prefer you didn't use this method & added domain login here, but stackoverflow can only teach so much..
        return fileHandles;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(fileHandles.size());
        dest.writeLongArray(toPrimitives(fileHandles));
    }

    private static long[] toPrimitives(List<Long> list) {
        return toPrimitives(list.toArray(new Long[list.size()]));
    }

    public static long[] toPrimitives(Long... objects) {
        long[] primitives = new long[objects.length];
        for (int i = 0; i < objects.length; i++)
            primitives[i] = objects[i];

        return primitives;
    }

    public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
        @Override
        public FileHandles createFromParcel(Parcel in) {
            return new FileHandles(in);
        }

        @Override
        public FileHandles[] newArray(int size) {
            return new FileHandles[size];
        }
    };
}

可序列化的 (强制使用实现了 Serializable 接口的 ArrayList (而不是 List)

输入:

    Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
    intent.putExtra("handles", new ArrayList<Long>());

输出:

    ArrayList handles = (ArrayList) intent.getSerializableExtra("handles");

谢谢你的回答。我研究了Parcelable选项,但它似乎比丑陋的转换更糟糕。Serializable选项似乎是解决问题最简单的方法。 - Kevin DiTraglia
Serializable 强制使用 ArrayList 是更简单的选项。Parcelable 是 Android 版本的 Serializable,它被优化用于移动设备和大数据集。我总是建议使用 Serializable,但如果您的列表中有数千个项目并且需要频繁传递,我建议您研究一下 Parcelable,以考虑性能提升。 - Blundell
谢谢,我会记住的。我认为在我的使用情况下它会没问题,只有5-10个长值。 - Kevin DiTraglia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接