Problem when updating ListActivity using a custom adapter

0

I'm working on an application where populo a ListActivity using data of a SQLite created by the program itself. When you add items to the database, the list is updated automatically, but when you remove it, the list is not updated.

I insert new items into a Activity separate from the main, but at the time of deleting items, I do the same within a DialogFragment called within ListActivity . Here's my code:

package activities;

import adapters.ItemListAdapter;
import android.app.FragmentManager;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ListView;
import br.bravosix.historico.R;
import classes.Database;
import classes.ListItem;
import fragments.QuickViewFragment;

public class ActivityList extends ListActivity {

    ItemListAdapter adapter;


    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // carrega os itens salvos no banco de dados quando
        // a tela é criada
        loadItems();
    }

    // re-carrega os itens após o resumo da activity

    public void onResume() {
        super.onResume();
        loadItems();
    }


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


    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.menu_list_add) {
            // activity responsável por adicionar novos itens
            // ao banco de dados
            Intent addItem = new Intent(this, ActivityNewItem.class);
            startActivity(addItem);
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        ListItem item = (ListItem) l.getItemAtPosition(position);
        FragmentManager fm = getFragmentManager();
        QuickViewFragment quickView = QuickViewFragment.newInstance(item);
        quickView.show(fm, "tag_quick_view");
        // testei o notifyDataSetChanged aqui e não funcionou, o mesmo
        // ocorreu quando usei a função loadItems();
        adapter.notifyDataSetChanged();
    }

    public void loadItems() {
        Database db = new Database(this);
        adapter = new ItemListAdapter(this, db.readItems());
        setListAdapter(adapter);
    }
}

What do I need to do so that when QuickViewFragment is closed, the list is updated?

    
asked by anonymous 01.06.2014 / 06:42

1 answer

1

I'll suggest a solution to the Fragment problem but I have another suggestion to improve how you update your list in ActivityList .

I understand that you refresh the list whenever your Activity is summarized, this includes calling the onResume resulting from the ActivityNewItem completion, but there is a negative effect in this way due to the% with%. When your app goes back and forth, you go to Activity without needing it.

In the case of BD there is no interference in the life cycle of Fragment so Activity is not called. And it's also no use calling onResume because at that moment notifyDataSetChanged will be displayed, and the user has not yet excluded the item, given the asynchronicity.

1. Updating the list after iteration with QuickViewFragment

In the Fragment method, I would make a small change. If you do not know what to do with Fragment, you should know that it is a good way to do it.

The onListItemClick in code is the form of communication (avoiding coupling) between Listener and onAttach . With the interface methods the ActionListener can notify the Fragment of the interactions made that need updating in Activity .

It would look something like:

Class Fragment :

public class ActivityList extends ListActivity implements QuickViewFragment.ActionListener {

// ... Codigo e mais codigo

    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);

        ListItem item = (ListItem) l.getItemAtPosition(position);
        FragmentManager fm = getFragmentManager();
        QuickViewFragment quickView = QuickViewFragment.newInstance(item);
        quickView.setActionListener(this);
        // Sendo generico, pois nao sei que acoes poderiam ocorrer no fragment 
        quickView.show(fm, "tag_quick_view");
        // Nao precisa do adapter.notifyDataSetChanged();
    }

    @Override
    public void onDelete(Item item) {
        atualizaLista(item);
        // O metodo atualiza pode ser de duas formas:
        // Ou ele remove o item da lista, sem ir no banco.
        // Ou ele atualiza toda a lista, select no banco.
    }

    // Demais metodos da interface

}

Class Activity :

public class QuickViewFragment extends DialogFragment {

    private ActionListener mAl;

    @Override
    public View onCreateView(...) {
        // ...
    }

    public interface ActionListener {
        public void onDelete(...);
        public void onUpdate(...);
        // ... O que mais quiser
    }

    private void ActionListener al; // Getter/Setter suprimidos

    @Override
    public void onAttach(Activity a) {
        super.onAttach(a);

        if(a instanceof ActionListener) {
            mAl = (ActionListener) a;
        }

        // Apenas uma sugestão de uso, nao precisa ser assim...
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if(al != null) {
            //Chamar alguma acao do Listener
        }

        super.onDismiss(dialog);
    }

    @Override
    public void onDestroyView(...) {
        al = null; // Evitar MemoryLeak
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // ... Código

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        // ... Mais Código

        // Na configuracao do botao negativo (utilizar o ClickListener para chamar a Callback.
        builder.setNegativeButton(R.string.quickview_delete,
            new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // Codigo de deleção no BD...
                    if(mAl != null) {
                        mAl.onDelete(...);
                    }
                }
            }
        );
}

In the interface metrics you would update your list.

The Activity method belongs to the ActivityList lifecycle, it is called when QuickViewFragment is "attached" to onAttach , before being added. I recommend reading the documentation on the lifecycle of Fragment .

The Fragment method is called when Activity of Fragment is being closed. Have a look at the method documentation onDismiss .

2. Updating the list after ActivityNewItem returns

When you call an activity using Dialog , there is an alternate form that indicates that you are expecting a return result from DialogFragment . The DialogFragment.onDismiss(DialogInterface dialog) , and to get the return you need to overwrite the Intent method of your ActivityNewItem to know whether or not to refresh the list.

In method startActivityForResult (Intent intent, int requestCode) of onActivityResult (int requestCode, int resultCode, Intent data) I would make a small change:

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.menu_list_add) {
        // activity responsável por adicionar novos itens
        // ao banco de dados
        Intent addItem = new Intent(this, ActivityNewItem.class);
        startActivityForResult(addItem, 999, null); // Guarde o numero 999 pra depois
        return true;
    }

    return super.onOptionsItemSelected(item);
}

And I would add this method of class ListActivity :

protected void onActivityResult(int requestCode /* 999 */, int resultCode, Intent data) {
    if(requestCode == 999 && resultCode == RESULT_OK) {
        // Atualiza lista, pois o retorno foi positivo...
    }

    super.onActivityResult(...);
}

In onOptionsItemSelected put something like:

@Override
public void finish() {
    if(houveAlteracao) { // Se houve alguma atualizacao nessa 'Activity'
        setResult(RESULT_OK, dado);
        // Diz para a Activity que me chamou
        // Que houve uma alteracao de dados aqui...
    }

    super.finish();
}

I believe that with this working, you do not have to use the ListActivity method to refresh the list, unless some external app modifies its ListActivity .

The answer was long, but I hope it helps ...

    
01.06.2014 / 17:51