5

So I have a weird problem. I have 2 Activities I'm working on. One of the Activities displays a ListView whose data is grabbed via a long Extra I use to fetch the results via a WHERE clause in the database.query. The other Activity is called when a ListView item is clicked, allowing someone to add something to the database for the ListView.

The activity names are DaysActivity.java (the activity with the listview) and DayAddActivity.java (the Activity that allows someone to add a day, which then shows up in the DaysActivity.java ListView).

The problem I'm having is, when I finish() DayAddActivity.java it goes back to DaysActivity and the ListView is still there fully populated. However, if I hit the back button in DayAddActivity.java (the button to the left of the title in the action bar with my app icon), when it goes back to DaysActivity.java, the ListView is empty/gone.

Heres the code for both:

DaysActivity.java:

package com.gauvion.gfit;

import android.annotation.SuppressLint;
import android.app.ListActivity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class DaysActivity extends ListActivity {

    private DaysDataSource datasource;
    private SimpleCursorAdapter dataAdapter;
    private boolean isEditing = false;
    private Toast toast_deleted;
    private String[] columns = new String[] { MySQLiteHelper.COLUMN_NAME, MySQLiteHelper.COLUMN_DAY };
    private int[] to;
    private long routineDataID;
    private String routineDataName;

    @SuppressLint("ShowToast")
    @Override
    public void onCreate(Bundle savedInstanceState) {       
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_days); 

        routineDataID = getIntent().getLongExtra("routineDataID", 0);
        routineDataName = getIntent().getStringExtra("routineDataName");
        setTitle(routineDataName);

        toast_deleted = Toast.makeText(this, "", Toast.LENGTH_SHORT);
        datasource = new DaysDataSource(this);
        datasource.open();

        Cursor cursor = datasource.fetchAllDays(routineDataID);
        to = new int[] { R.id.listitem_day_name, R.id.listitem_day_day };
        dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_day, cursor, columns, to, 0);
        setListAdapter(dataAdapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {     
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.activity_days, menu);
        return true;        
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {     
        Cursor cursor = datasource.fetchAllDays(routineDataID);
        switch (item.getItemId()) {
        case R.id.button_days_add:
            Intent startDayAdd = new Intent(this, DayAddActivity.class);
            startDayAdd.putExtra("routineDataID", routineDataID);
            this.startActivity(startDayAdd);
            return true;

        case R.id.button_days_edit:
            to = new int[] { R.id.listitem_day_edit_name, R.id.listitem_day_edit_day };
            dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_day_edit, cursor, columns, to, 0);
            setListAdapter(dataAdapter);

            isEditing = true;
            invalidateOptionsMenu();
            return true;

        case R.id.button_days_edit_done:
            to = new int[] { R.id.listitem_day_name, R.id.listitem_day_day };
            dataAdapter = new SimpleCursorAdapter(this, R.layout.listitem_day, cursor, columns, to, 0);
            setListAdapter(dataAdapter);

            isEditing = false;
            invalidateOptionsMenu();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        menu.findItem(R.id.button_days_edit).setVisible(!isEditing);
        menu.findItem(R.id.button_days_edit_done).setVisible(isEditing);

        return true;
    }

    @Override
    protected void onResume() {
        datasource.open();
        Cursor cursor = datasource.fetchAllDays(routineDataID);
        dataAdapter.changeCursor(cursor);

        super.onResume();
    }

    @Override
    protected void onPause() {
        datasource.close();
        super.onPause();
    }

} 

DayAddActivity.java:

package com.gauvion.gfit;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import android.support.v4.app.NavUtils;

public class DayAddActivity extends Activity {
    private RoutinesDataSource datasource;
    private EditText dayName;
    private Spinner dayDay;
    private Button saveButton;
    private long routineDataID;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_day_add);
        routineDataID = getIntent().getLongExtra("routineDataID", 0);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_day_add, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void cancelDay(View view) {
        this.finish();
    }

}

The cancelDay() function is called when a "Cancel" button is clicked in activity_day_add.xml. Like I said, when I click the "Cancel" button inside of DayAddActivity.java, it goes back to DaysActivity.java and the ListView is fine. All data is there. However, if I press the back button in the action bar (the button containing a back arrow and my app icon beside the title of the Activity) the ListView for DaysActivity.java is empty/gone, and the title is also empty (because this is also generated through an Extra String value).

scarhand
  • 4,069
  • 23
  • 60
  • 91
  • it could be that `onResume()` isn't being called when back is pressed. you could put in a log command to check. if so, you could try overriding `onBackPressed()` to call the methods that you find working. – mango Dec 26 '12 at 18:43
  • I did notice something; when `DayAddActivity` is `finish()`ed, it seems that `DaysActivity` is not recreated. However when the back button is pressed, it's like it is recreated. I noticed this by the animations. Since it is recreated when the back button is pressed, is it possible this is happening because the Extras are not being passed? Notice how `DaysActivity` utilizes Extras in order to display the Title & ListView. By "back button" I don't mean the hardware button, I mean the icon with the arrow beside the title. – scarhand Dec 26 '12 at 18:46
  • OK, so its the "up" button I'm talking about here that is causing the issue. – scarhand Dec 26 '12 at 18:52
  • 1
    sorry for the initial error. we are talking about `case android.R.id.home: NavUtils.navigateUpFromSameTask(this);` correct? I'm not familiar with the method, but i would just think to use the `finish()` instead, if it was working previously. again, i'd use log commands to ascertain what's being called or not or to even make sure the intents have values. – mango Dec 26 '12 at 18:57
  • yeah, i ended up just using `finish()` instead. thank you. – scarhand Dec 26 '12 at 19:09

2 Answers2

0

Your cursors are not managed by the activity, this can cause a memory leak or even ANR. You should consider using a loader to populate a list using a cursor. You can find an example here :http://developer.android.com/guide/components/loaders.html.

Loaders work better as they don't freeze the app when the connexion to the database is obtained and they will be passed from one instance of your activity to another, preventing memory leaks and reusing resources.

But again, as in your previous post : Extras seem to be lost onResume(), you should understand the link between onSaveInstanceState and onCreate to pass arguments to the future self of your activity. Look at this post, the answer with the biggest score : onSaveInstanceState () and onRestoreInstanceState ().

Community
  • 1
  • 1
Snicolas
  • 36,854
  • 14
  • 106
  • 172
  • I read up on it a bit more, and it seems I was misusing the instancestate functions. Apparently they are not intended to preserve variables like that between activities, rather contain things like incomplete form data. I could be mistaken. – scarhand Dec 26 '12 at 19:21
  • also in order to have the Activity manage the cursor do I simply called `startManagingCursor()`? i'll have to look into that further... – scarhand Dec 26 '12 at 19:26
  • also the datasource is closed in the `onPause()` function, is that not good enough to prevent memory leaks?? – scarhand Dec 26 '12 at 19:27
  • Here is a thread for your on the topic of closing cursors : http://stackoverflow.com/questions/11262627/android-database-connections-and-cursors-oh-my – Snicolas Dec 27 '12 at 06:47
  • im still worried about your comment on memory leaks and ANR. can you please look at the new question i posted on the matter: http://stackoverflow.com/questions/14061821/ensuring-my-cursor-is-closed – scarhand Dec 27 '12 at 21:58
  • Did you look at the thread in my previous comment on this page. It's really worth it. Please, consider using a loader, it's rather easy and much better suited for what you do, more modern, more robust. That would solve everything. – Snicolas Dec 27 '12 at 22:03
0

It seems like your Context has some problems in "this.startActivity(startDayAdd);" line. try using "DaysActivity.this.startActivity(startDayAdd);". if it doesnot work then use breakpoints to see line by line execution.

Adnan Amjad
  • 2,423
  • 1
  • 18
  • 29
  • Using `this` as a context does the exact same thing. I believe I'd only have to use the name of the activity as a context if that activity was different from the one it was being called within. – scarhand Dec 26 '12 at 22:35
  • did you debug your app? If it is not the context problem then it is sure that your cursor creating a problem. – Adnan Amjad Dec 27 '12 at 06:34