2014-10-07 2 views
9

В настоящее время я пишу приложение, которое вытаскивает массив longs с сервера через json, а затем передает этот список из одной активности в другую. Основной скелет выглядит следующим образом:Sane way from ArrayList <Long> через намерение

public void onResponse(Map result) 
{ 
    ArrayList handles= (ArrayList)result.get("fileHandles"); 

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

Итак, первая проблема становится очевидной, только методы putExtra являются putIntegerArrayListExtra, putStringArrayListExtra, putCharSequenceArrayListExtra и putParcelableArrayListExtra. Мышление Долго, вероятно, было бы разумным, я был неправ, что он не работает (даже если я использую ArrayList<Long>). Затем я подумал, что просто пройду длинный [], но я не вижу прямого преобразования, чтобы перейти от ArrayList<Long> к длинному [], который примет intent.putExtra. Это было решение, которое я наконец закончил с:

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> от активности к активности может быть настолько сложной. Есть ли более очевидное решение, которое мне не хватает?

+0

FWIW: 'Long.parseLong (handles.get (i) .toString());' может быть записано как '(long) (Long) handles.get (i)' ('(long)' фактически необязательно в контексте), когда источником является «ArrayList ». Он использует dowcast, а затем явный (или неявный) un-autobox вместо Long-> String-> long. – user2864740

+0

@ user2864740 Проблема заключается в том, что 'handles.get (i)' возвращает мне целое число, если оно меньше 2 миллиардов или около того, что приводит к недействительному приведению, если я использую этот код. –

ответ

9

Вы можете использовать его как дополнительно Serializable. ArrayList является Serializable и Long расширяет Number, который также реализует Serializable:

// 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");  
+0

Я не вижу 'putSerializable' в качестве опции на' Intent'. –

+0

Простите, я смотрел на «Bundle», а не на «Intent». См. Редактирование. :) – kcoppock

+0

Получил, намного проще, спасибо. Очень приятно удалить весь этот ужасный код, который я только что написал. –

2

Два варианта: Используйте 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]; 
     } 
    }; 
} 

Сериализуемый (вынуждены использовать ArrayList, который реализует Serializable (List не делает)

в:

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

из:

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

Спасибо за ответ.Я рассмотрел возможный вариант, но он казался хуже, чем уродливое обращение. Параметры 'Serializable', похоже, являются самым простым решением проблемы. –

+0

'Serializable' с принудительным использованием' ArrayList' является более простым вариантом. «Parcelable» - версия Androids от 'Serializable' http://developer.android.com/reference/android/os/Parcelable.html, оптимизированная для мобильных и больших наборов данных. Я бы всегда рекомендовал «Serializable», но если у вас есть 1000 элементов в вашем списке и передайте его много, я бы порекомендовал вам исследование «Parcelable» для оценки эффективности работы – Blundell

+0

Спасибо, я буду иметь в виду. Я думаю, что в моем случае это будет хорошо, это не более 5-10 длинных значений. –

Смежные вопросы