0

I am working on a simple application that passes a parcelable from one activity to another. In MainActivity, I have a LinkedList that holds the information taken from the parcelable. However, each time i return to MainActivity, the Object previously stored in the LinkedList (Parcelable) is deleted. What am I doing wrong? I have spent literally the past 3 days trying to figure out why it isn't saving anything but the logic looks solid. So I updated to use startActivityForResult and now the Parcelable in MainActivity is NULL.

public class MainActivity extends Activity {

int tasks;
final static String TASK_KEY = "newTask";
final static String INDEX_KEY = "LLIndex";
Task t;
ScrollView scrollView;
LinearLayout taskHolder;
LinkedList<Task> taskList = new LinkedList<Task>();

@Override
protected void onCreate(Bundle savedInstanceState) {

    Log.d("In onCreate", "here");

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    TextView tvCounter = (TextView) findViewById(R.id.textView1);

    taskHolder = (LinearLayout) findViewById(R.id.linearScroll);

    //Checks for parcelable
    if(getIntent().hasExtra(Create.TASK_KEY)){
        Log.d("Task", "You've got mail!");
        Task t = (Task)getIntent().getExtras().getParcelable(Create.TASK_KEY);
        taskList.add(t);
        addNewTask(t);

    }

    Log.d("LL size", Integer.toString(tasks));

    tasks = taskList.size();

    tvCounter.setText(Integer.toString(tasks) + " " + getApplicationContext().getResources().getString(R.string.tv_task));

    Button plusButton = (Button) findViewById(R.id.button1);

    plusButton.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Intent i = new Intent(MainActivity.this, Create.class);
            startActivity(i);
        }
    });
}

    void addNewTask(Task t) {

        tasks++;

        Log.d("In addNewTask method", t.toString());

        LinearLayout newTaskLayout = new LinearLayout(getApplicationContext());
        newTaskLayout.setOrientation(LinearLayout.VERTICAL);
        LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        newTaskLayout.setLayoutParams(params);
        //int bottom = (int) getResources().getDimension(R.dimen.margin_bottom);
        //int left = (int) getResources().getDimension(R.dimen.margin_left);
        //params.setMargins(left, 0, 0, bottom);

        TextView tvTitle = new TextView(getApplicationContext());
        TextView tvDate =  new TextView(getApplicationContext());
        TextView tvTime =  new TextView(getApplicationContext());

        tvTitle.setTextColor(Color.BLACK);
        tvDate.setTextColor(Color.BLACK);
        tvTime.setTextColor(Color.BLACK);

        tvTitle.setTypeface(tvTitle.getTypeface(), Typeface.BOLD);

        tvTitle.setText(t.getName());
        tvDate.setText(t.getDate());
        tvTime.setText(t.getTime());

        newTaskLayout.addView(tvTitle);
        newTaskLayout.addView(tvDate);
        newTaskLayout.addView(tvTime);  

        //params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        //params.setMargins(0, 0, 0, 0);
        //tvDate.setLayoutParams(params);
        //tvTime.setLayoutParams(params);

        //tvTitle.setTextSize(getResources().getDimension(R.dimen.size_of_text));


        taskHolder.addView(newTaskLayout);


        final int index = ((ViewGroup) newTaskLayout.getParent()).indexOfChild(newTaskLayout);

        newTaskLayout.setOnClickListener(new View.OnClickListener() {//bind listener

        @Override
        public void onClick(View v) {
        // TODO Auto-generated method stub
        Intent i = new Intent(MainActivity.this,Display.class);
        i.putExtra(TASK_KEY, taskList.get(index));
        i.putExtra(INDEX_KEY, index);
        startActivity(i);
        }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d("CheckStartActivity","onActivityResult and resultCode = "+resultCode);
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode==1){
            Toast.makeText(this, "Pass", Toast.LENGTH_LONG).show();
            Log.d("Task", "You've got mail!");

            if(getIntent().hasExtra(Create.TASK_KEY)){
            Task t = (Task)getIntent().getExtras().getParcelable(Create.TASK_KEY);
            taskList.add(t);
            addNewTask(t);
            }
            Log.d("LL size", Integer.toString(tasks));

            tasks = taskList.size();

            tvCounter.setText(Integer.toString(tasks) + " " + getApplicationContext().getResources().getString(R.string.tv_task));

        }
        else{
            Toast.makeText(this, "Fail", Toast.LENGTH_LONG).show();
        }
        }
    }

Create Class:

public class Create extends Activity{

private int year;
private int month;
private int day;
private String name, date, time, priority;
final static String TASK_KEY = "newTask";
static final int PICK_CONTACT_REQUEST = 1;

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

    final Calendar cal = Calendar.getInstance();

    //Current Date
    year  = cal.get(Calendar.YEAR);
    month = cal.get(Calendar.MONTH);
    day   = cal.get(Calendar.DAY_OF_MONTH);

    final EditText etTitle = (EditText) findViewById(R.id.editText1);
    final EditText etDate  = (EditText) findViewById(R.id.editText2);
    final EditText etTime  = (EditText) findViewById(R.id.editText3);

    final RadioGroup rg = (RadioGroup) findViewById(R.id.radioGroup1);

    //int selectedId = rg.getCheckedRadioButtonId();
    //final RadioButton radioSelected = (RadioButton) findViewById(selectedId);

    Button save = (Button) findViewById(R.id.button1);

    save.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            //Get checked radio button
            RadioButton rb = (RadioButton) findViewById(rg.getCheckedRadioButtonId());

            // TODO Auto-generated method stub
            name = etTitle.getText().toString();
            date = etDate.getText().toString();
            time = etTime.getText().toString();
            priority = (String) rb.getTag();

            Task t = new Task(name, date, time, priority);

            Log.d("task", t.toString());

            Intent i = new Intent(Create.this, MainActivity.class);
            i.putExtra(TASK_KEY, t);    //Puts new Task object into Intent to send
            setResult(1,i);
            finish();
        }
    });

    etDate.setKeyListener(null);
    etTime.setKeyListener(null);

    final DatePickerDialog.OnDateSetListener datePick = new DatePickerDialog.OnDateSetListener() {

        @Override
        public void onDateSet(DatePicker view, int year, int monthOfYear,
                int dayOfMonth) {
            // TODO Auto-generated method stub
            cal.set(Calendar.YEAR, year);
            cal.set(Calendar.MONTH, monthOfYear);
            cal.set(Calendar.DAY_OF_MONTH, dayOfMonth);
            updateLabel();
        }

        private void updateLabel() {
            // TODO Auto-generated method stub
            String myFormat = "MM/dd/yy"; //In which you need put here
            SimpleDateFormat sdf = new SimpleDateFormat(myFormat, Locale.US);

            etDate.setText(sdf.format(cal.getTime()));
        }

    };

    etDate.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {


            //Do whatever
            new DatePickerDialog(Create.this, datePick, cal.get(Calendar.YEAR), 
                    cal.get(Calendar.MONTH),
                    cal.get(Calendar.DAY_OF_MONTH)).show();
        } 
    });

    etTime.setOnClickListener(new View.OnClickListener()  {


        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            Calendar curTime = Calendar.getInstance();
            int hour = curTime.get(Calendar.HOUR_OF_DAY);
            int minute = curTime.get(Calendar.MINUTE);
            TimePickerDialog tp;

            tp = new TimePickerDialog(Create.this, new TimePickerDialog.OnTimeSetListener() {
                @Override
                public void onTimeSet(TimePicker timePicker, int selectedHour, int selectedMinute) {

                    String am_pm;
                    String minuteStr;
                    Log.d("hour", Integer.toString(selectedHour));


                    if (selectedHour == 0){
                        selectedHour = 12;
                        am_pm = "AM";
                    }else if(selectedHour == 12){
                        selectedHour = 12;
                        am_pm = "PM";
                    }else if(selectedHour > 12) {
                       selectedHour -= 12;
                       am_pm = "PM";
                    }else{
                        am_pm = "AM";
                    }

                    if(selectedMinute < 10){
                        minuteStr = "0" + Integer.toString(selectedMinute);
                    }else{
                        minuteStr = Integer.toString(selectedMinute);
                    }

                    etTime.setText( selectedHour + ":" + minuteStr + " " + am_pm);


                }
            }, hour, minute, false);//Yes 24 hour time
            tp.setTitle("Set Time");
            tp.show();
        }
    });

}
}
Hermes Trismegistus
  • 515
  • 2
  • 5
  • 16

1 Answers1

0

If I understand the question correctly, you have a list of messages in MainActivity, and you're starting the Create intent to create a new message. Then, on save, you're starting a new MainActivity with the new message to add to the list.

The problem with this approach is that a new MainActivity instance will be created each time, with a new (empty) LinkedList in it.

I would look at using startActivityForResult() to run the Create activity, and use setResult() and finish() within Create to return the new message.

You should also look at saving the contents of the list within 'onSaveInstanceState', to handle the destruction and recreation of your MainActivity (e.g. when the user rotates their device).

Alan
  • 2,962
  • 2
  • 15
  • 18
  • The funny thing is I noticed each time that the List wouldn't increase, I just didn't understand why. I figured if I set the LinkedList outside of the onCreate, it would store it since I was just placing a new Activity in front of it. – Hermes Trismegistus Jan 29 '15 at 08:17
  • I updated the code as advised but now the Parcelable is returning NULL in MainActivity. – Hermes Trismegistus Jan 29 '15 at 08:27
  • Have you overridden `onActivityResult()` in your `MainActivity` to pick up the result from `Create`? – Alan Jan 29 '15 at 08:32
  • Regarding your first comment... the only safe way to handle Activities is to assume Android is going to completely destroy it every time it pauses, and ensure you can completely recreate it from scratch if/when Android recreates it at a later time. – Alan Jan 29 '15 at 08:33
  • Hi Alan, I updated the code in the post, and yes I overrode it and wrote my own methods but when it goes to pull the parcel it's not there. – Hermes Trismegistus Jan 29 '15 at 08:34
  • Hi. Without seeing the updated code, I'm not sure what's happening. As long as you are starting `Create` with `startActivityForResult()`, and within `Create`, you're calling setResult() with an Intent populated with the new message, followed by `finish()` to pop `Create` off the stack and return to your `MainActivity`, you should be able to get the result in the `onActivityResult` callback. – Alan Jan 29 '15 at 09:35
  • Hi Alan, I meant that I updated the code in the question post too. :-) Now if I try to get the parceable using Task t = (Task)getIntent().getExtras().getParcelable(Create.TASK_KEY); I get a NULL pointer exception for the statement. – Hermes Trismegistus Jan 29 '15 at 09:37
  • Ah, I didn't notice that. Don't use getIntent() to get the intent, use the one passed into the method as an argument. getIntent() will return the intent used to start your activity, not the one returned from the child activity. – Alan Jan 29 '15 at 09:41
  • Sorry to sound so ignorant, but I've had no sleep and I only have experience using getIntent. What do you mean use the one passed as a method? – Hermes Trismegistus Jan 29 '15 at 09:47
  • Gotta love those all-nighter code problems! :). Within onActivityResult, the `data` argument is the Intent you want to use. Simply use `Task t = (Task)data.getExtras().getParcelable(Create.TASK_KEY);`. – Alan Jan 29 '15 at 09:50
  • 1
    You saved my life! Why is it that get intent worked before to pull the parcelable? – Hermes Trismegistus Jan 29 '15 at 09:53
  • It worked before because you were starting a new empty activity with the parcelable in the intent (so the startup intent retrieved by getIntent() was the one carrying the data). When you use startActivityForResult, it's a bit like making a function call, and the result from the call is the completely separate `data` Intent within onActivityResult(). – Alan Jan 29 '15 at 10:04