Search code examples
androidandroid-loader

using loader to automatically update listview when a change happens to a database table


in my Application i have an Activity that has a ListView and a button.
i am using loader to automatically loading data to listview from my table in the database.
and i am using the button to change the table rows.
i want the loader to automatically load the data from table when a change happens to the table.
right now my code loads the data into listview but it doesn't update it when table changes after that.
here are my classes :
item

public class Item {
    public int id;
    public String name;
} 

MainActivity :

public class MainActivity extends Activity implements
        LoaderManager.LoaderCallbacks<List<Item>> {
        ItemAdapter adapter;
        List<Item> items;
        Button button;
        TextView tv;
        ListView listview;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tv = (TextView) findViewById(R.id.tv);
        button = (Button) findViewById(R.id.button);
        listview = (ListView) findViewById(R.id.listview);  
        items = new ArrayList<Item>();
        adapter = new ItemAdapter(this, items);
        listview.setAdapter(adapter);
        getLoaderManager().initLoader(0, savedInstanceState, this).forceLoad();
    }
    //button code for changing db
    public void change(View view) {
       ItemHelper helper = new ItemHelper(this);
       Item item = new Item();
       item.name = "Samsung P6800";
       helper.insert(item);
    }
    @Override
    public Loader<List<Item>> onCreateLoader(int id, Bundle args) {

        final ItemHelper helper = new ItemHelper(getApplicationContext());
        return new AsyncTaskLoader<List<Item>>(MainActivity.this) {

            @Override
            public List<Item> loadInBackground() {
                return helper.read();
            }

        };

    }

    @Override
    public void onLoadFinished(Loader<List<Item>> loader, List<Item> data) {
        adapter.addAll(data);
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(Loader<List<Item>> loader) {
        adapter.clear();
        adapter.notifyDataSetChanged();
    }

ItemHelper

public class ItemHelper {

    public static final String DB_NAME = "Test";
    private static Context m_context;
    private static SQLiteDatabase m_db;
    private static DatabaseHelper m_helper;
    String[] columns = { "id", "name" };

    public  ItemHelper(Context context) {
        m_context = context;
        m_helper = new DatabaseHelper(m_context, DB_NAME, null, 1);
    }

    private static class DatabaseHelper extends SQLiteOpenHelper {

        public DatabaseHelper(Context context, String name,
                CursorFactory factory, int version) {
            super(context, DB_NAME, null, 1);

        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            // TODO Auto-generated method stub

        }

    }

    public void insert(Item item) {
        m_db = m_helper.getWritableDatabase();
        ContentValues initialValues = new ContentValues();
        initialValues.put("name", item.name);
        m_db.insert("item", null, initialValues);
        m_db.close();
    }

    public List<Item> read() {
        List<Item> items = new ArrayList<Item>();
        m_db = m_helper.getReadableDatabase();
        Cursor cursor = m_db.query("item", columns, null, null, null, null,
                null);
        if (cursor.moveToFirst()) {
            do {
                Item item = new Item();
                item.id = cursor.getInt(cursor.getColumnIndexOrThrow("id"));
                item.name = cursor.getString(cursor
                        .getColumnIndexOrThrow("name"));

                items.add(item);
            } while (cursor.moveToNext());
        }
        m_db.close();
        return items;
    }
}

ItemAdapter

public class ItemAdapter extends ArrayAdapter<Item> {

    private Context context;
    private List<Item> items;
    private LayoutInflater vi;

    public ItemAdapter(Context context, int resource) {
        super(context, resource);
        // TODO Auto-generated constructor stub
    }

    public ItemAdapter(Context context, List<Item> items) {
        super(context, 0, items);
        this.context = context;
        this.items = items;
        vi = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = convertView;

        Item item = items.get(position);
        if (item != null) {
            view = vi.inflate(R.layout.item_info, parent, false); // custom xml
                                                                    // for
                                                                    // desired
                                                                    // view

            TextView tv1 = (TextView) view.findViewById(R.id.tvID);
            tv1.setText(""+item.id);
            TextView tv2 = (TextView) view.findViewById(R.id.tvName);
            tv2.setText(item.name);

        }
        return view;
    }

    @Override
    public Item getItem(int position) {
        return items.get(position);
    }

}


how can i do it ? ( i don't want to use content providers )


Solution

  • finally i used ContentProviders to solve this issue.
    i created a method inside my database helper class that returns a Cursor according to it's parameters,
    and used it inside ContentProvider to get Data.

    public Cursor getCursor(int status, boolean isAccepted) {
        m_db = m_helper.getReadableDatabase();
        String sql = "SELECT id as _id , rid , isaccepted , status FROM torder";
        Cursor cursor = m_db.rawQuery(sql, null);
        return cursor;
    }
    

    also in helper when i insert data to db i notify the content provider :

    public void notifyProvider(int status) {
        ContentValues values = new ContentValues();
        values.put("status", status);
        Uri uri = m_context.getContentResolver().insert(
                OrderProvider.CONTENT_URI, values);
    
    }
    
    public void insert(Order order) {
        int flag = (order.isAccepted()) ? 1 : 0;
    
        String[] args = { String.valueOf(order.getId()),
                String.valueOf(order.getR_id()), String.valueOf(flag),
                String.valueOf(order.getStatus()) };
        m_db.execSQL(
                "INSERT OR REPLACE INTO torder(id,rid,isaccepted,status) VALUES(?,?,?,?)",
                args);
        // save to orderdetails
        List<OrderDetails> orderDetailsList = order.getOrders();
        OrderDetailsHelper helper = OrderDetailsHelper.getInstance(m_context);
        helper.open();
        helper.insertAll(orderDetailsList);
        helper.close();
        notifyProvider(1);
    }