通过 2nd activity 中的 Parcelable 通过 intent 从检索到的 ArrayList 中获取 ArrayList 的元素

Get elements of ArrayList from retrieved ArrayList via intent via Parcelable in 2nd activity

我正在尝试构建一个简单的 android 来模拟用卡片学习词汇。为了获得最终的应用程序,我将通过学习新事物和添加新事物来逐步添加功能和复杂性。

我要告诉你我被困在哪里,但首先,到目前为止,这是我的应用程序应该做的(我离我想要的地方还很远,但是你不必担心这个。):

此时应用程序应该执行以下操作:

2) 在 PracticeActivity

我目前停留在 2) c),因为该应用程序只能按照上述索引 0 的方式工作。只有 VocCard card0 = vocCardList1.get( 0);有效,vocCardList1.get(1),或 vocCardList1.get(2);不要,尽管 1 和 2 在 ArrayList 边界内。

奇怪的是,使用索引 1 和索引 2 的运行时异常消息不一样:

与 vocCardList1.get(1):java.lang.ClassCastException: java.lang.String cannot be cast to com.undiclosed.smartcards.VocCard

与 vocCardList1.get(2):java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.undisclosed.smartcards.VocCard.returnVocForeign()' on a null object reference

问题:

为什么我不能按照预期的方式访问 ArrayList 的元素?当我在网上搜索时,我可能在寻找错误的东西。

MainActivity.java:

package com.undisclosed123.smartcards;

import android.content.Intent;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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

public class MainActivity extends AppCompatActivity {
    private List<VocCard> vocCardList;
    private String[] voc_f = {"bread","apple","water"};
    private String[] voc_n = {"pain","pomme","eau"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Create VocCards and add to List
        vocCardList = new ArrayList<VocCard>();
        VocCard[] voc1 = new VocCard[3];
        Parcel in = Parcel.obtain();

        for(int i = 0; i < 3; i++){

            voc1[i] = new VocCard(in);
            voc1[i].setVocForeign(voc_f[i]);
            voc1[i].setVocNative(voc_n[i]);
            vocCardList.add(voc1[i]);
        }
        // Create Intent and assign the parcelable List for sending to second activity on btn click
        Button startBtn = (Button) findViewById(R.id.button);
        startBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             @SuppressWarnings("unchecked")
             public void onClick(View v) {
                 Intent intent = new Intent(MainActivity.this, PracticeActivity.class);
                 intent.putParcelableArrayListExtra("voc1",(ArrayList)vocCardList);
                 getApplicationContext().startActivity(intent);
             }
        });
    }
}

及以下,PracticeActivity.java:

(很抱歉被注释掉的大部分内容,我想这可以帮助传达我进一步的意图 class)

package com.undisclosed123.smartcards;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.util.ArrayList;

public class PracticeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_practice);

        // Get the Intent that started this activity and extract the string
        Intent intent = getIntent();
        final ArrayList<VocCard> vocCardList1 = intent.getParcelableArrayListExtra("voc1");     // 

        //Get the Data from the VocCards
        //VocCard card4count = vocCardList1.get(2);
       // card4count.increaseCount(); 
        //int count = card4count.getCount();
       /* if(count >= vocCardList1.size()){
            // TODO
             //Create new intent for EndPracticeActivity

            //makeshift statement
            count--;

        }*/
        VocCard card0 = vocCardList1.get(2); 
       // VocCard card1 = vocCardList1.get(1);
        String test1 = card0.returnVocForeign();
       // card0.increaseCount();
     //   String test1 = "test1";

        //Make a TextView display the transfered String
        TextView textView = findViewById(R.id.textView);
        textView.setText(test1);

        //Create another intent that recalls same activity recursively
        Button nextBtn = (Button) findViewById(R.id.button2);
        nextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            @SuppressWarnings("unchecked")
            public void onClick(View v) {
                Intent intent = new Intent(PracticeActivity.this, PracticeActivity.class);
                intent.putParcelableArrayListExtra("voc1",(ArrayList)vocCardList1);
                getApplicationContext().startActivity(intent);
            }
        }); /**/

    }
}

最后,VocCard.java:

package com.undisclosed123.smartcards;

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

public class VocCard implements Parcelable {
    private String voc_foreign;
    private String voc_native;
    private boolean learned;
    private int error_level;
    private static int counter;

    public String returnVocForeign(){
        return voc_foreign;
    }

    public void setVocForeign(String voc_f){
        voc_foreign = voc_f;
    }

    public String returnVocNative(){
        return voc_native;
    }

    public void setVocNative(String voc_n){
        voc_native = voc_n;
    }

    public boolean checkLearned(){
        return learned;
    }

    public int getErrorLevel(){
        return error_level;
    }

    public void makeLearned(){
        learned = true;
    }

    public void increaseErrorLevel(){
        error_level++;
    }

    public int getCount(){
        return counter;
    }

    public void increaseCount(){
        counter++;
    }

    public VocCard(Parcel in) {
        voc_foreign = in.readString();
        voc_native = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(voc_foreign);
        dest.writeString(voc_native);
        dest.writeInt((Boolean) learned ? 1 : 0);
        dest.writeInt(error_level);
    }

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

    public static final Creator<VocCard> CREATOR = new Creator<VocCard>() {
        @Override
        public VocCard createFromParcel(Parcel in) {
            return new VocCard(in);
        }

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

问题在于将数据写入 Parcel 并从中读取数据。

public class VocCard implements Parcelable {

    ...
    ...

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(voc_foreign);
        dest.writeString(voc_native);
        dest.writeInt(learned ? 1 : 0);
        dest.writeInt(error_level);
    }

    /**
    * This constructor is invoked by the method 
    * createFromParcel(Parcel source) of the object CREATOR.
    * 
    * The order and number of writing and reading data to and from   
    * Parcel should be same 
    **/
    private VocCard(Parcel in) {
        voc_foreign = in.readString();
        voc_native = in.readString();
        learned = in.readInt() == 1;
        error_level = in.readInt();
    }

    /**
    * A constructor that initializes the VocCard object. 
    **/
    VocCard(String voc_foreign, String voc_native) {
        this.voc_foreign = voc_foreign;
        this.voc_native = voc_native;
    }

    ...
    ...

}

MainActivity 内部 onCreate

几乎没有变化
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

    ...
    ...

    //Create VocCards and add to List
    mVocCardList = new ArrayList<>(3);

    for (int i = 0; i < 3; i++) {
        mVocCardList.add(new VocCard(voc_f[i], voc_n[i]));
    }

    Button startBtn = (Button) findViewById(R.id.button);
    startBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent = new Intent(MainActivity.this, PracticeActivity.class);
            intent.putParcelableArrayListExtra("voc1", (ArrayList<? extends Parcelable>) mVocCardList);
            startActivity(intent);
        }
    });
}

现在在PracticeActivity

中获取VocCard列表
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {

    ...
    ...

    final ArrayList<VocCard> vocCardList = getIntent().getParcelableArrayListExtra("voc1");

    final VocCard card = vocCardList.get(2);
    String test = card.getVocForeign();

    ... 
    ...

}