【问题标题】:Add Items to an ArrayList<String> that has been passed between Activities将项目添加到已在活动之间传递的 ArrayList<String>
【发布时间】:2014-07-28 19:25:58
【问题描述】:

我在 StackOverflow 和互联网上四处查看并尝试了一些方法,但它们都给了我同样的普遍问题。

我有一个 ArrayList,我在一个活动中创建,然后通过(另一个活动或 2 个其他活动,具体取决于用户的选择)并在每个活动(包括创建数组列表的活动)中让用户选择一个组中的单个按钮。选择按钮后,我有一个侦听器,它创建一个简单的字符串,然后将该字符串添加到 ArrayList,或者至少这是我想要它做的。

  1. 我曾尝试使用Serialized 类将同一个列表传递给它需要通过的所有活动
  2. 我已经尝试在每个类中创建一个新的 ArrayList,从通过 intent.putExtra() 发送然后接收的上一个类中复制一个,以便可以将其复制到一个新的 ArrayList 中以执行相同的操作,直到它到达最后的活动。
  3. 我试图理解 Parcleable 的实现,但这对我来说似乎太多了(我现在不擅长这个)。

每当我尝试使用 ArrayList 的 .add() 方法(或第二次尝试完成此操作时使用 .addAll() 时,所有这些都给了我相同的 NullPointerException

非常感谢您向初学者提供的任何建议以及解释!如果需要我可以放代码!!

【问题讨论】:

  • 您需要发布您的代码和 LogCat,以便我们了解它发生的原因。在没有任何代码的情况下,这里没有人有魔杖知道发生了什么。
  • 检查这个答案stackoverflow.com/a/5374603/3820750也许可以帮助你。
  • 如果您没有 ArrayList 的自定义对象,我认为您不需要 Parcelable。您获得NullPointerException 的原因可能与您的Activity 生命周期有关。确保您以正确的方法复制/创建实例,并且不要忘记切换活动时,您之前的活动可能会被杀死并且您可能会丢失数据。
  • 你不需要了解 Parcelable 的实现,你只需要把它扔到parcelabler.com 并得到一个这样的自动实现

标签: java android android-intent android-activity arraylist


【解决方案1】:

首先,你应该使用Parcelable,在这种情况下效率更高。 查看此链接以了解“为什么”:
https://medium.com/@theblackcat102/passing-object-between-activity-using-gson-7dfa11d74e06

其次,我会这样做:

public class ActivityOne extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_one);
        Intent intent = new Intent(this, ActivityTwo.class);
        ArrayList<Person> strings = new ArrayList<Person>(Arrays.asList(new Person("Bob"),new Person("Dude")));
        Bundle bundle = new Bundle();
        bundle.putParcelableArrayList(ActivityTwo.PARCELABLE_KEY,strings);
        intent.putExtras(bundle);
        startActivity(intent);
    }
}


public class ActivityTwo extends Activity {
    public static final String PARCELABLE_KEY = "array_key";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_two);
        if (getIntent() != null) {
            ArrayList<Person> persons = getIntent().getParcelableArrayListExtra(PARCELABLE_KEY);
            Log.d("test", persons.toString());
        }
    }
}

public class Person implements Parcelable {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }


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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
    }

    public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {
        public Person createFromParcel(Parcel source) {
            return new Person(source);
        }

        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    private Person(Parcel in) {
        this.name = in.readString();
    }
}

另外,不要害怕 Parcelables!而作为一个优秀的开发者,你应该偷懒,然后使用 Parcelable 生成器比如:
http://www.parcelabler.com/

只需复制您的 POJO 类并生成(还有一个 Android Studio 插件)。

最后,不要忘记您不能在 2 个活动之间传递无限数据。您还可以考虑将数据放入数据库。

【讨论】:

  • 如果它只在少数活动之间共享,这是您想要的实现。您不会遇到任何数据损坏/同步问题,但是会增加一些不明显的开销和一些样板文件。
  • 非常感谢您!我相信 Parcelable 是解决此问题的最佳方法,但是即使在生成器和您的示例之后我仍然迷路了,所以现在我将不得不使用我已经制定的第二个答案,只需将列表复制到每个活动中都有一个新列表。但是,我将重新审视 Parcelables,因为我希望我所做的事情尽可能高效!再次感谢!
【解决方案2】:

我整理了一个将数组列表传递给其他活动并向其添加项目的快速示例。

public class FirstActivity extends Activity {

    public static final String EXTRA_FIRST_ARRAY = "ExtraFirstArray";

    private static final String TAG = FirstActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ArrayList<String> firstArrayList = new ArrayList<String>();

        firstArrayList.add("First Activity Test1");
        firstArrayList.add("First Activity Test2");
        firstArrayList.add("First Activity Test3");

        Log.d(TAG, "First Array List: ");

        for (String value : firstArrayList) {
            Log.d(TAG, "Value: " + value);
        }

        Intent intent = new Intent(this, SecondActivity.class);
        intent.putStringArrayListExtra(EXTRA_FIRST_ARRAY, firstArrayList);
        startActivity(intent);
    }
}

public class SecondActivity extends Activity {

    public static final String EXTRA_SECOND_ARRAY = "ExtraSecondArray";

    private static final String TAG = SecondActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getIntent().getExtras() != null) {

            final ArrayList<String> firstArrayList = getIntent().getStringArrayListExtra(FirstActivity.EXTRA_FIRST_ARRAY);

            ArrayList<String> secondArrayList = new ArrayList<String>();

            secondArrayList.addAll(firstArrayList);

            secondArrayList.add("Second Activity Test1");
            secondArrayList.add("Second Activity Test2");
            secondArrayList.add("Second Activity Test3");

            Log.d(TAG, "Second Array List: ");

            for (String value : secondArrayList) {
                Log.d(TAG, "Value: " + value);
            }

            Intent intent = new Intent(this, ThirdActivity.class);
            intent.putStringArrayListExtra(EXTRA_SECOND_ARRAY, secondArrayList);
            startActivity(intent);
        }
    }
}

public class ThirdActivity extends Activity {

    private static final String TAG = ThirdActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getIntent().getExtras() != null) {

            final ArrayList<String> secondArrayList = getIntent().getStringArrayListExtra(SecondActivity.EXTRA_SECOND_ARRAY);

            ArrayList<String> thirdArrayList = new ArrayList<String>();

            thirdArrayList.addAll(secondArrayList);

            thirdArrayList.add("Third Activity Test1");
            thirdArrayList.add("Third Activity Test2");
            thirdArrayList.add("Third Activity Test3");

            Log.d(TAG, "Third Array List: ");

            for (String value : thirdArrayList) {
                Log.d(TAG, "Value: " + value);
            }
        }
    }
}

【讨论】:

  • 很好的例子。我唯一的建议是在调用活动中使用 startActivityForResult() 以便列表可以向后传递,然后在接收者中覆盖 finish() 以在它们退出时将编辑后的 ​​ArrayList 传回,以便开始的 Activity 可以看到对列表所做的更改(假设这是必要的......)
【解决方案3】:

如果您想在活动之间共享一些数据,我个人建议您将它们作为应用程序对象上的一个字段,以便您需要扩展应用程序类。

public class MyApplication extend Application{

private List<SomeData> data;

@overrite
public void onCreate(){
super.onCreate();
data = new ArrayList<SomeData>();
}

public List<SomeData> getData(){

return data
}
}

在清单文件中,您必须在应用程序 xml-tag 中配置您的应用程序类

<application
android:name:"package.name.MyApplication">
</application>

最后在你的活动中,你可以通过调用来访问它们:

((MyApplication)getApplication()).getData();

通过这种方式,您不会在序列化/反序列化时消耗资源,并且您可以在应用程序上下文中全局访问。请注意不要过度这样做,因为这些数据将独立于任何活动占用内存。但是如果打算持久化一些你会经常从不同的地方访问的数据,与序列化或通过 Parcelable 接口相比,这是一个优化的解决方案。

【讨论】:

  • 这个解决方案有很多问题。我会建议反对它,除非: - 当应用程序上下文存在时,您需要保留一些东西。当应用程序保留在“最近”中时,这基本上是正确的。 - 您可以控制数据的修改方式。每当他们公开每个人都可以访问的列表时,我已经看到这种情况失控了。您可能会遇到数据损坏/同步问题。所以只有在绝对必要时才这样做,如果你只需要将它从一个活动发送到另一个活动,我会建议 Parcelable。
  • 从性能的角度来看,我发现它是一个很好的解决方案。如果您在列表中有数千个项目,则可打包成为一项昂贵的操作,特别是当您必须经常访问来自不同活动的数据时。如果程序员知道他们在做什么,就不会有失控的风险。无论如何都可能发生数据同步问题。再次由程序员决定
  • 是的,这对于您提到的特定情况非常有用。当您有数千个元素需要保留到给定数量的活动时。开销随着列表的增长而增长。我同意,这取决于开发人员,许多滥用应用程序对象的数据非常小,这些数据很少被用户甚至可能不经常使用的活动使用。还有其他人只是为了懒惰而将其用作标准。所以最好知道什么时候使用这种方法。
【解决方案4】:

您也可以使用自定义意图:

public class SharedIntent extends Intent {
    private List list;

    public void putArrayList(List list){
        this.list = list;
    }

    public List getList(){
        return list;
    }
}

发送:

public class SenderActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedIntent intent = new SharedIntent();
        intent.putArrayList(new ArrayList<String>());
    }
}

检索:

public class GettingActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getIntent() instanceof SharedIntent) {
            SharedIntent intent = (SharedIntent) getIntent();
            ArrayList<String> list = (ArrayList<String>) intent.getList();
        }
    }
}

【讨论】:

  • 如果我没记错你不能使用自定义意图。 Intent 本身是在 android 中重新创建的,所以无论你创建什么自定义,它都会在某个时刻被转换为 Intent。而在另一端,该列表将不存在
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
相关资源
最近更新 更多