Wątek przeniesiony 2018-11-19 20:35 z Java przez Ktos.

Android korzystanie z Parcelable

0

Witam
Próbuje nauczyć się korzystać z przesyłania danych pomiędzy aktywnościami w aplikacji. Do tego celu zdecydowałem się użyć klasy Parcelable.
Chcę mieć mozliwość przenosić dane z ArrayList<Barcode> z głównej aktywności do innej i potem z powrotem do głównej.
Gdzieś mam bład, tylko nie wiem gdzie i utknąłem, proszę o pomoc.
Błąd:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.krzys.savetest/com.krzys.savetest.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.util.ArrayList.get(int)' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4053)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4096)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1516)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.util.ArrayList.get(int)' on a null object reference
at com.krzys.savetest.MainActivity.onActivityResult(MainActivity.java:52)
at android.app.Activity.dispatchActivityResult(Activity.java:6915)

Klasa MainActivity:

public class MainActivity extends AppCompatActivity {

    ArrayList<Barcode> scanedBarcodes;

    Button btnViewPage, btnTypePage;

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

        scanedBarcodes = new ArrayList<Barcode>();

        btnTypePage = (Button) findViewById(R.id.btnTypePage);
        btnTypePage.setOnClickListener((view) -> {
            Intent intent = new Intent(MainActivity.this, TypeActivity.class);
            intent.putParcelableArrayListExtra("codes", scanedBarcodes);
            startActivity(intent);
            startActivityForResult(intent, 1);
        });
        btnViewPage = (Button) findViewById(R.id.btnViewPage);
        btnViewPage.setOnClickListener((view) -> {
            Intent intent = new Intent(MainActivity.this, ViewActivity.class);
            startActivity(intent);
        });

        loadBarcodesDataFromMemory();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode==RESULT_OK && requestCode==1){
            Intent intent = this.getIntent();
            scanedBarcodes = intent.getParcelableArrayListExtra("codes");
            Toast.makeText(MainActivity.this, scanedBarcodes.get(0).getScanedBarcodes(), Toast.LENGTH_SHORT).show();
        }
    }

    void loadBarcodesDataFromMemory(){
//        scanedBarcodes.clear();

        File file = getApplicationContext().getFileStreamPath("BarcodesData.txt");
        String lineFromFile;

        if (file.exists()){
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(openFileInput("BarcodesData.txt")));

                while ((lineFromFile = reader.readLine()) != null){

                    Barcode barcode = new Barcode(lineFromFile);
                    scanedBarcodes.add(barcode);
                }

                reader.close();

            }catch (IOException e){
                Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(MainActivity.this, "File don't exist!", Toast.LENGTH_SHORT);
        }
    }
}

Klasa TypeActivity:

public class TypeActivity extends AppCompatActivity {

    EditText etTypedString;
    Button btnAddData;

    ArrayList<Barcode> scanedBarcodes;

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

        Intent intent = this.getIntent();
        scanedBarcodes = intent.getParcelableArrayListExtra("codes");

        etTypedString = (EditText) findViewById(R.id.etTypedString);
        btnAddData = (Button) findViewById(R.id.btnAddData);
        btnAddData.setOnClickListener((view)-> addDataToArray());
    }

    @Override
    public void onBackPressed() {
//        super.onBackPressed();
        Intent intent = new Intent();
        intent.putParcelableArrayListExtra("codes", scanedBarcodes);
        setResult(RESULT_OK, intent);
        finish();
    }

    void addDataToArray(){
        String typedString = etTypedString.getText().toString();

        Barcode scanedBarcode = new Barcode(typedString);
        scanedBarcodes.add(scanedBarcode);
    }
}

Klasa Barcode:

public class Barcode implements Parcelable {

    private String scanedBarcodes;

    public Barcode(String scanedBarcodes) {
        this.scanedBarcodes = scanedBarcodes;
    }

    public Barcode() {

    }

    public String getScanedBarcodes() {
        return scanedBarcodes;
    }

    public void setScanedBarcodes(String scanedBarcodes) {
        this.scanedBarcodes = scanedBarcodes;
    }

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

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

    @SuppressWarnings("unused")
    public static final Parcelable.Creator<Barcode> CREATOR = new Parcelable.Creator<Barcode>() {
        @Override
        public Barcode createFromParcel(Parcel in){
            Barcode barcode = new Barcode();
            barcode.setScanedBarcodes(in.readString());
            return barcode;
        }

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

0
            scanedBarcodes = intent.getParcelableArrayListExtra("codes");
            Toast.makeText(MainActivity.this, scanedBarcodes.get(0).getScanedBarcodes(), Toast.LENGTH_SHORT).show();

Stawiam, że w pierwszej linii dostajesz null zamiast listy, w drugiej wyskakuje NPE na get(0)

0

tak, ale czemu listy nie dostaję? źle zaimplementowałem Parcelable w Barcode? czy coś innego?

0

ok, znalazłem już rozwiązanie i wszytko działa jak należy. Może się komus to przyda:
Poprawna klasa Barcode:

public class Barcode implements Parcelable {

    private String scanedBarcodes;

    public Barcode(String scanedBarcodes) {
        this.scanedBarcodes = scanedBarcodes;
    }

    public String getScanedBarcodes() {
        return scanedBarcodes;
    }

    public void setScanedBarcodes(String scanedBarcodes) {
        this.scanedBarcodes = scanedBarcodes;
    }

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

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

    protected Barcode(Parcel in) {
        this.scanedBarcodes = in.readString();
    }

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

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

wysyłanie do aktywności:

btnViewPage.setOnClickListener((view) -> {
            Intent intent = new Intent(MainActivity.this, ViewActivity.class);
            intent.putParcelableArrayListExtra("myDataKey", scanedBarcodes);
            startActivity(intent);
        });

odczyt:

scanedBarcodes = new ArrayList<Barcode>();
        scanedBarcodes = getIntent().getParcelableArrayListExtra("myDataKey");
1

wez uzyj https://github.com/f2prateek/dart zamiast pisac ten bjler-kod

2
  1. Tak jak napisał pozdro, warto pomyśleć nad zastąpieniem tego nadmiarowego kodu przy użyciu bibliotek np https://github.com/johncarl81/parceler
  2. Alternatywa #1: użycie pluginu do automatycznego generowania tego kodu: https://github.com/mcharmas/android-parcelable-intellij-plugin
  3. Alternatywa #2: jak najmniej stosować parcelable, u mnie w aplikacji odszedłem od takiego rozwiązania całkowicie i jestem bardzo zadowolony. Nauczony doświadczeniem : Im mniej androida tym lepiej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1