So my app uses a local SQLite db through a contentProvider
In it's mainActivity I have a listView displaying the contents of a table from the above DB.
I use a custom adapter to display the listview. Each item has a button in it's (custom) layout, that when pressed, shows a custom dialog that inserts a new record in that table, then the dialog gets dismissed.
In order to achieve this behavior, I placed the button click handler inside the customAdapter.
I would like to be able to refresh the listView after the inserting is done (so when dialog is dismissed)
How can I achieve this?
I should probably need to call notifyDataSetChanged somehow from inside the custom Adapter but I can't.
In short, my custom adapter looks like this:
public class DisplayStuffAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> id;
private ArrayList<String> iduser;
private ArrayList<String> product;
public DisplayStuffAdapter(Context c){
this.mContext = c;
}
public DisplayStuffAdapter(Context c, ArrayList<String> id, ArrayList<String> userid, ArrayList<String> product) {
this.mContext = c;
this.id = id;
this.userid = userid;
this.product = product;
}
public int getCount() {
return id.size();
}
public Object getItem(int position) {
return null;
}
public long getItemId(int position) {
return 0;
}
public class Holder {
TextView txt_id;
TextView txt_userid;
TextView txt_prod;
}
public View getView(int pos, View child, ViewGroup parent) {
Holder mHolder;
LayoutInflater layoutInflater;
if (child == null) {
layoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
child = layoutInflater.inflate(R.layout.myitem, null);
mHolder = new Holder();
mHolder.txt_id = (TextView) child.findViewById(R.id.tv_MkId);
mHolder.txt_userid = (TextView) child.findViewById(R.id.tv_MkUserId);
mHolder.txt_prod = (TextView) child.findViewById(R.id.tv_MkProduct);
child.setTag(mHolder);
} else {
mHolder = (Holder) child.getTag();
}
mHolder.txt_id.setText(id.get(pos));
mHolder.txt_userid.setText(userid.get(pos));
mHolder.txt_prod.setText(product.get(pos));
Button bt = (Button) child.findViewById(R.id.itemButton);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
LayoutInflater li = LayoutInflater.from(mContext);
final View promptsView = li.inflate(R.layout.bid_dialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
alertDialogBuilder.setView(promptsView);
alertDialogBuilder.setMessage("Input data")
.setIcon(R.drawable.add_red_24)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
})
.setPositiveButton("Add new record", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ContentValues values = new ContentValues();
values.put(MyProvider.TCOL_ID, myid);
values.put(MyProvider.TCOL_OTHERID, Integer.toString(getActiveUserId()));
Uri uri = mContext.getContentResolver().insert(MyProvider.CONTENT_URI_TABLE, values);
values = new ContentValues();
dialogInterface.dismiss();
}
}
}
});
// create alert dialog
final AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
alertDialog.setCanceledOnTouchOutside(false);
....
}
});
....
I remove some parts from the code to make it more readable.
Now, in my MainActivity, I set the adapter like this:
public class MainActivity extends Activity{
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> userid = new ArrayList<String>();
private ArrayList<String> product = new ArrayList<String>();
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fillListView();
}
...
private void fillListView(){
id.clear();
userid.clear();
product.clear();
String[] col = {MyProvider.TCOL_ID_ID, MyProvider.TCOL_USERID, MyProvider.TCOL_PROD};
String where = "done = 1";
Cursor mCursor = MainActivity.this.getContentResolver().query(MyProvider.CONTENT_URI_TABLE, col, where, null, MyProvider.TCOL_DATE + " desc");
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
id.add(Integer.toString(mCursor.getInt(0)));
userid.add(Integer.toString(mCursor.getInt(1)));
product.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
}
DisplayStuffAdapter disadpt = new DisplayStuffAdapter(MainActivity.this,id,userid,product);
disadpt.notifyDataSetChanged();
ListView lv = (ListView) findViewById(R.id.mylistView);
lv.setAdapter(disadpt);
}
So this all works great, except that when I add a new record to the table using the customdialog described above... the dialog closes, and the listview remains unchanged.
How can I refresh the listView?
In general, when you're querying data from a DB, you should use ContentProvider and CursorLoader. You can configure your content provider to automatically notify loaders when some data changes, using ContentResolver notifyChange() method. Place the call to this method in your ContentProvider implementation (for example after the insert). This is an example of adapter you can use (but you can use SimpleCursorAdapter providing a view binder too).
public class CustomCursorAdapter extends CursorAdapter {
private LayoutInflater mInflater;
public CustomCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
if(cursor.getPosition()%2==1) {
view.setBackgroundColor(context.getResources().getColor(R.color.background_odd));
}
else {
view.setBackgroundColor(context.getResources().getColor(R.color.background_even));
}
TextView content = (TextView) view.findViewById(R.id.row_content);
content.setText(cursor.getString(cursor.getColumnIndex(Table.CONTENT)));
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return mInflater.inflate(R.layout.listitem, parent, false);
}
}
public class DisplayStuffAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String> id;
private ArrayList<String> iduser;
private ArrayList<String> product;
public DisplayStuffAdapter(Context c){
this.mContext = c;
}
public void loadData(){
id.clear();
userid.clear();
product.clear();
String[] col = {MyProvider.TCOL_ID_ID, MyProvider.TCOL_USERID, MyProvider.TCOL_PROD};
String where = "done = 1";
Cursor mCursor = MainActivity.this.getContentResolver().query(MyProvider.CONTENT_URI_TABLE, col, where, null, MyProvider.TCOL_DATE + " desc");
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
id.add(Integer.toString(mCursor.getInt(0)));
userid.add(Integer.toString(mCursor.getInt(1)));
product.add(mCursor.getString(2));
} while (mCursor.moveToNext());
}
}
notifyDataSetChanged();
}
...
}
public class MainActivity extends Activity{
private DisplayStuffAdapter disadpt = null;
ContentObserver displayStuffObserver = new ContentObserver(new Handler()){
#Override
public void onChange(boolean selfChange) {
if(disadpt != null) {
disadpt.loadData();
}
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
disadpt = new DisplayStuffAdapter(this);
ListView lv = (ListView) findViewById(R.id.mylistView);
lv.setAdapter(disadpt);
disadpt.loadData();
getContentResolver().registerContentObserver(MyProvider.CONTENT_URI_TABLE,true, displayStuffObserver);
}
}
Do not forget to unregister your content observer
First of all, I am not getting why you are sending three different arraylists to the adapter. You can simply make a modal class having all the fields that you require in your adapter. Considering your current scenario it will be something like this
public class ModalClass {
private String id = "";
private String userId = "";
private String product = "";
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
So this is your modal class with getters and setters. Now all you have to do is you have to make an ArrayList of this modal class like this
List<ModalClass> modalClassList=new ArrayList<ModalClass>();
and you have to set all the data that you want to display in your list in this arraylist by making use of modal class setter functions. Like this
if (mCursor != null) {
if (mCursor.moveToFirst()) {
do {
ModalClass modalClass=new ModalClass();
modalClass.setId(Integer.toString(mCursor.getInt(0)));
modalClass.setUserId(Integer.toString(mCursor.getInt(1)));
modalClass.setProduct(mCursor.getString(2));
modalClassList.add(modalClass);
} while (mCursor.moveToNext());
}
}
and now you have your arraylist ready, so you can set it to your listview like this
ListView lv = (ListView) findViewById(R.id.mylistView);
DisplayStuffAdapter disadpt = new DisplayStuffAdapter(MainActivity.this,modalClassList);
lv.setAdapter(disadpt);
And accordingly you have to modify your adapter constructor which i think you can do by your own.
Also how to set values in your adapter, you can make use of your modal class getter methods like this.
ModalClass modalClass=modalClassList.get(pos);
mHolder.txt_id.setText(modalClass.getId());
mHolder.txt_userid.setText(modalClass.getUserId());
mHolder.txt_prod.setText(modalClass.getProduct());
Now when you want to insert a new row in your adapter, you have to simply create an object of ModalClass and set all the new values in that like we have done in our MainActivity class and then finally add that to your modalClassList followed by notifyDataSetChanged();
ModalClass modalClass=new ModalClass();
modalClass.setId(yourNewInsertedRowId);
modalClass.setUserId(yourNewInsertedRowUserId);
modalClass.setProduct(yourNewInsertedRowProduct);
modalClassList.add(modalClass);
notifyDataSetChanged();
And this time your list will be notify for sure. Cheers :)
Related
I am creating a demo Android app which has a ListView displaying in a fragment. Each List item has a text and a delete button, and the items are stored in SQLite database.
I am having trouble understanding how to delete the corresponding item from the database when the delete button is clicked. I searched for various ways online, and could not figure out how to get the _ID value (set to autoincrement) of the row item in the DB, so that the item could be deleted.
The custom Adapter class
public class CustomListAdapter extends ArrayAdapter<DataModel> implements View.OnClickListener{
private ArrayList<DataModel> dataSet;
Context mContext;
private TaskHelper_tab1 mHelper;
public CustomListAdapter(#NonNull Context context, int resource, #NonNull ArrayList<DataModel> data) {
super(context, resource, data);
this.dataSet = data;
this.mContext=context;
}
private static class ViewHolder {
TextView txtName;
Button btn;
}
#Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(position);
DataModel dataModel=(DataModel)object;
switch (v.getId())
{
case R.id.task_delete:
Snackbar.make(v, "Release date " +dataModel.getName(), Snackbar.LENGTH_LONG)
.setAction("No action", null).show();
break;
}
}
private int lastPosition = -1;
#SuppressLint("NewApi")
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// Get the data item for this position
final DataModel dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
final ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.task_list_long_term_item, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.task_title);
viewHolder.btn = (Button) convertView.findViewById(R.id.task_delete);
result=convertView;
convertView.setTag(viewHolder);
viewHolder.btn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
int id2 = (int) getItemId(position);
Toast.makeText(mContext,id2 + " Button clicked" + position,Toast.LENGTH_SHORT).show();
deleteTask(id2);
notifyDataSetChanged();
}
});
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
lastPosition = position;
viewHolder.txtName.setText(dataModel.getName());
return convertView;
}
public void deleteTask(int position){
mHelper = new TaskHelper_tab1(getContext());
SQLiteDatabase db = mHelper.getWritableDatabase();
db.execSQL("DELETE FROM " + Task_tab1.TaskEntry.TABLE + " WHERE " + Task_tab1.TaskEntry._ID + "= '" + position + "'");
db.close();
}
}
The fragment code
public class fragment_tab1 extends Fragment{
//for db tasks
EditText editText = null;
private TaskHelper_tab1 mHelper;
FloatingActionButton fab_tab1;
private PopDialog.PopDialogListener listener; //listener to pass the text to parent activity
private TextView textViewDescr;
private CustomListAdapter mAdapter;
private View view;
private ListView list_calllog;
private ArrayList<DataModel> callLog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mHelper = new TaskHelper_tab1(getContext());
list_calllog = (ListView) getActivity().findViewById(R.id.list);
updateUI(); //this works -- keep this to initially populate the UI on opening app
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
if(view==null)
{
view=inflater.inflate(R.layout.fragment_tab1, container,false);
}
else
{
ViewGroup parent = (ViewGroup) view.getParent();
parent.removeView(view);
}
callLog= new ArrayList<>();
callLog.add(new DataModel("Apple Pie", null)); //maybe add button here
callLog.add(new DataModel("Banana Bread",null ));
CustomListAdapter adapter=new CustomListAdapter(getActivity(),R.layout.task_list_long_term_item,callLog);
list_calllog=(ListView)view.findViewById(R.id.list);
list_calllog.setAdapter(adapter);
fab_tab1 = (FloatingActionButton) view.findViewById(R.id.fab_tab1);
fab_tab1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View tab1) {
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.pop_dialog_layout, null);
alert.setTitle("info")
.setMessage("dialog box message")
.setView(view)
.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String edittext_descr = editText.getText().toString();
applyTexts(edittext_descr);
Toast toast = Toast.makeText(getContext(), "adadadaa", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
}
);
alert.show();
editText = view.findViewById(R.id.edit_text);
}
});
return view;
}
#Override
public void applyTexts(String edittext_descr) {
String task = String.valueOf(edittext_descr);
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Task_tab1.TaskEntry.COL_TASK_TITLE, task);
db.insertWithOnConflict(Task_tab1.TaskEntry.TABLE, null, values, SQLiteDatabase.CONFLICT_REPLACE);
db.close();
updateUI();
}
private void updateUI() {
ArrayList<DataModel> taskList = new ArrayList<>();
SQLiteDatabase db = mHelper.getReadableDatabase();
Cursor cursor = db.query(Task_tab1.TaskEntry.TABLE,
new String[] {Task_tab1.TaskEntry._ID, Task_tab1.TaskEntry.COL_TASK_TITLE}, null, null, null, null, null);
while(cursor.moveToNext()){
int index = cursor.getColumnIndex(Task_tab1.TaskEntry.COL_TASK_TITLE);
//add new task
String str = cursor.getString(index);
DataModel dm = new DataModel(str,null );
taskList.add(dm);
}
if(mAdapter == null){
mAdapter = new CustomListAdapter(getActivity(), R.layout.task_list_long_term_item, taskList );
list_calllog.setAdapter(mAdapter);
} else {
mAdapter.clear();
mAdapter.addAll(taskList);
mAdapter.notifyDataSetChanged();
}
cursor.close();
db.close();
}
}
I searched for various ways online, and could not figure out how to get the _ID value (set to autoincrement) of the row item in the DB, so that the item could be deleted.
Aren't you querying the ID attribute for the object when you read the data from the database? If not, do that and store in the DataModel. Then when you get the object that was clicked, you have the ID:
DataModel dataModel=(DataModel)object;
// TODO: Use dataModel.getId()
Hope that helps!
I want to retrieve data from two fields from prepopulate sqlite database. The fields are Organization Name (org_name) and Contact Number (contact_no). After that I need to assign org_name data to a large text field and contact_no to small text field in my custom list view.
I have tried this only with one field. It's working fine. But when I'm trying to retrieve two fields it's not working. This is what I tried. Please help me to solve this issue.
ContactView class
public class ContactView extends Activity {
private ListView listView;
private ListView listView1;
List<Organization> rowItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view);
DBAccess databaseAccess = DBAccess.getInstance(this);
databaseAccess.open();
List<String> quotes = databaseAccess.getQuotes(getIntent().getStringExtra("ID_EXTRA"));
databaseAccess.close();
List<Organization> rowItem=new ArrayList<Organization>();
for(String quote:quotes){
Organization temp=new Organization(quote);
rowItem.add(temp);
}
listView = (ListView)findViewById(R.id.listView);
CustomListViewAdapter adapter = new CustomListViewAdapter(this,
R.layout.single_row_item, rowItem);
listView.setAdapter(adapter);
}
Database Access Class
public class DBAccess {
private SQLiteOpenHelper openHelper;
private SQLiteDatabase database;
private static DBAccess instance;
String passedVar = null;
private ListView listView;
public DBAccess(Context context) {
this.openHelper = new HelloDatabase(context);
}
public static DBAccess getInstance(Context context) {
if (instance == null) {
instance = new DBAccess(context);
}
return instance;
}
public void open() {
this.database = openHelper.getWritableDatabase();
}
public void close() {
if (database != null) {
this.database.close();
}
}
public List<String> getQuotes(String id) {
List<String> list = new ArrayList<>();
Integer value;
if (id != null) {
Cursor cursor = database.rawQuery("SELECT org_name,contact_no FROM org_name WHERE category_id = \"" + id + "\"", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(cursor.getString(0));
list.add(cursor.getString(cursor.getColumnIndex("contact_no")));
cursor.moveToNext();
}
cursor.close();
}
return list;
}}
Bean class
public class Organization {
public String title;
public String telenum;
public Organization(String title,String telenum) {
this.title = title;
this.telenum=telenum;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTelenum(){
return telenum;
}
public void setTelenum(String telenum){
this.telenum=telenum;
}
}
CustomListViewAdapter class
public class CustomListViewAdapter extends ArrayAdapter<Organization> {
Context context;
public CustomListViewAdapter(Context context, int layout,
List<Organization> items) {
super(context, layout, items);
this.context = context;
}
/*private view holder class*/
private class ViewHolder {
TextView txtTitle;
TextView txtTele;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Organization rowItem = getItem(position);
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.single_row_item, null);
holder = new ViewHolder();
holder.txtTitle = (TextView) convertView.findViewById(R.id.org_name);
holder.txtTele = (TextView) convertView.findViewById(R.id.tele_num);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
holder.txtTitle.setText(rowItem.getTitle());
holder.txtTele.setText(rowItem.getTelenum());
return convertView;
}}
Note : If any one facing the same issue, kindly use SimpleCursorAdapter. Its simple, easy to use and efficient. Find a simple example here or checkout my answer on this thread https://stackoverflow.com/a/37560755/5460053
It is not working for two fields because of the following lines in getQuotes() method of DBAccess class :
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
list.add(cursor.getString(0));//Adding org_name first. org_name is added at indexes : 0,2,4,...
list.add(cursor.getString(cursor.getColumnIndex("contact_no")));//Then adding contact_no. contact_no is added at indexes : 1,3,5,...
cursor.moveToNext();
}
Then while creating a datasource for the adapter, org_name and contact_no are added at alternate indexes
List<Organization> rowItem=new ArrayList<Organization>();
for(String quote:quotes){
Organization temp=new Organization(quote);//I wonder how this worked as there is only one contructor for Organization which is expecting 2 parameters
rowItem.add(temp);
}
Change your DBAccess class getQuotes() to this :
public List<Organization> getQuotes(String id) {
List<Organization> list = new ArrayList<>();
if (id != null) {
Cursor cursor = database.rawQuery("SELECT org_name,contact_no FROM org_name WHERE category_id = \"" + id + "\"", null);
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
Organization org = new Organization(cursor.getString(0),
cursor.getString(cursor.getColumnIndex("contact_no")));
list.add(org);
cursor.moveToNext();
}
cursor.close();
}
return list;
}
And change your ContactView Activity's onCreate() to this :
public class ContactView extends Activity {
private ListView listView;
private ListView listView1;
List<Organization> rowItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view);
DBAccess databaseAccess = DBAccess.getInstance(this);
databaseAccess.open();
List<Organization> rowItem = databaseAccess.getQuotes(getIntent().getStringExtra("ID_EXTRA"));
databaseAccess.close();
listView = (ListView)findViewById(R.id.listView);
CustomListViewAdapter adapter = new CustomListViewAdapter(this,
R.layout.single_row_item, rowItem);
listView.setAdapter(adapter);
}
I have a list view populated threw an SQlitedatabase but I need to pass to a detail activity from the list view. The problem is in passing the details from the listview activity to the detail activity because when I click the detail activity it gives me blank edit texts
Here is my listview activity:
public class consulter_note extends Activity implements AdapterView.OnItemClickListener{
ListView list;
SQLiteDatabase sqLiteDatabase;
DataBaseOperationstwo dataBaseOperationstwo;
Cursor cursor;
ListDataAdapter listDataAdapter;
String titre,objet;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_consulter_note);
list = (ListView) findViewById(R.id.listView);
listDataAdapter = new ListDataAdapter(getApplicationContext(),R.layout.notelist_row);
list.setAdapter(listDataAdapter);
list.setOnItemClickListener(this);
dataBaseOperationstwo = new DataBaseOperationstwo(getApplicationContext());
sqLiteDatabase = dataBaseOperationstwo.getReadableDatabase();
cursor = dataBaseOperationstwo.getInformations(sqLiteDatabase);
if (cursor.moveToFirst())
{
do
{
titre = cursor.getString(0);
objet = cursor.getString(1);
DataProvider dataProvider = new DataProvider(titre,objet);
listDataAdapter.add(dataProvider);
}while (cursor.moveToNext());
}
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(this, note_details.class);
startActivity(intent);
intent.putExtra("titre", titre);
intent.putExtra("objet", objet);
}
}
And here is my array adapter:
public class ListDataAdapter extends ArrayAdapter{
List list = new ArrayList();
public ListDataAdapter(Context context, int resource) {
super(context, resource);
}
static class LayoutHandler
{
TextView TITRE,OBJET;
}
#Override
public void add(Object object) {
super.add(object);
list.add(object);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
LayoutHandler layoutHandler;
if (row == null)
{
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.notelist_row,parent,false);
layoutHandler = new LayoutHandler();
layoutHandler.TITRE = (TextView) row.findViewById(R.id.titredemo);
layoutHandler.OBJET = (TextView) row.findViewById(R.id.objetdemo);
row.setTag(layoutHandler);
}
else
{
layoutHandler = (LayoutHandler) row.getTag();
}
DataProvider dataProvider = (DataProvider) this.getItem(position);
layoutHandler.TITRE.setText(dataProvider.getTitre());
layoutHandler.OBJET.setText(dataProvider.getObjet());
return row;
}
}
The data provider class used in the array adapter:
public class DataProvider {
private String titre,objet;
public DataProvider(String titre,String objet)
{
this.titre = titre;
this.objet = objet;
}
public String getTitre() {
return titre;
}
public void setTitre(String titre) {
this.titre = titre;
}
public String getObjet() {
return objet;
}
public void setObjet(String objet) {
this.objet = objet;
}
}
And finally my details activity. I'm only interested in the intent part; the rest has nothing to do with my problem:
public class note_details extends Activity {
ImageButton Del;
EditText PASSTITRE,USEROBJET;
String Passtitre,Userobjet;
DataBaseOperationstwo DOP;
Context CTX = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent =getIntent();
if(intent != null)
{
String objet = intent.getStringExtra("objet");
String titre= intent.getStringExtra("titre");
PASSTITRE.setText(objet);
USEROBJET.setText(objet);
}
setContentView(R.layout.activity_note_details);
Del = (ImageButton) findViewById(R.id.suppnote);
PASSTITRE = (EditText) findViewById(R.id.titree);
USEROBJET = (EditText) findViewById(R.id.objett);
Del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Passtitre = PASSTITRE.getText().toString();
Userobjet = USEROBJET.getText().toString();
DOP = new DataBaseOperationstwo(CTX);
DOP.deleteNote(DOP,Passtitre,Userobjet);
Toast.makeText(getBaseContext(),"note supprimé",Toast.LENGTH_LONG).show();
finish();
}
});
}
public void liste(View v)
{
Intent i = new Intent(this, consulter_note.class);
startActivity(i);
}
public void supprimer(View v)
{
}
}
My logcat doesn’t show any errors but the details activity shows with empty edittexts.
You should first add extras to the Intent and then fire it:
Intent intent = new Intent(this, note_details.class);
intent.putExtra("titre", titre);
intent.putExtra("objet", objet);
startActivity(intent);
Another thing worth mentioning is that you should avoid doing DB queries on the main thread, as it will slow down your app. Use Loaders, or just run queries on worker threads.
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 )
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);
}
Change your change method:
public void change(View view) {
ItemHelper helper = new ItemHelper(this);
Item item = new Item();
item.name = "Samsung P6800";
helper.insert(item);
getLoaderManager().restartLoader(0, null, this);
}
I have done the notepad tutorial from android webside. I added an own Module-Class. Now I also want to add a own baseadapter. But I have problems with the implementation.
My problem is the fillData() method. It is in the third code part. I am also not sure, if I will need a cursor?
I hope anybody can help me, to correct the fillData() method.
My Module-Class
public class Module {
private String title;
private String device_type;
private String home_code;
private String device_code;
public Module(String n, String m, String hc, String mc) {
title = n;
device_type = m;
home_code = hc;
device_code = mc;
}
public String getTitle() { return title; }
public String getDeviceType() { return device_type; }
public String getHomeCode() { return home_code; }
public String getDeviceCode() { return device_code; }
}
My Module Adapter:
public class ModuleAdapter extends BaseAdapter implements OnClickListener {
private Context context;
private List<Module> listModule;
public ModuleAdapter(Context context, List<Module> listModule) {
this.context = context;
this.listModule = listModule;
}
public int getCount() {
return listModule.size();
}
public Object getItem(int position) {
return listModule.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
Module entry = listModule.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.notes_row, null);
}
TextView tvTitle = (TextView) convertView.findViewById(R.id.text1);
tvTitle.setText(entry.getTitle());
TextView tvDeviceType = (TextView) convertView.findViewById(R.id.text2);
tvDeviceType.setText(entry.getDeviceType());
TextView tvHomeCode = (TextView) convertView.findViewById(R.id.text3);
tvHomeCode.setText(entry.getHomeCode());
TextView tvDeviceCode = (TextView) convertView.findViewById(R.id.text4);
tvDeviceCode.setText(entry.getDeviceCode());
return convertView;
}
#Override
public void onClick(View view) {
Module entry = (Module) view.getTag();
listModule.remove(entry);
// listModule.remove(view.getId());
notifyDataSetChanged();
}
private void showDialog(Module entry) {
// Create and show your dialog
// Depending on the Dialogs button clicks delete it or do nothing
}
}
The fillData() method from the main code:
private void fillData() {
//Cursor notesCursor = mDbHelper.fetchAllNotes();
//startManagingCursor(notesCursor);
final List<Module> from = new ArrayList<Module>();
from.add(new Module(NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_DEVICETYPE, NotesDbAdapter.KEY_HOMECODE, NotesDbAdapter.KEY_DEVICECODE));
// Now create a simple cursor adapter and set it to display
//SimpleCursorAdapter notes =
// new SimpleCursorAdapter(this, R.layout.notes_row, notesCursor, from, to);
//notes.setViewBinder(new ModuleViewBinder());
ModuleAdapter adapter = new ModuleAdapter(this, from);
setListAdapter(adapter);
}
Thanks a lot!
Felix
The problem is your data is in a database, so you should keep using the SimpleCursorAdapter as you were doing in the code you commented out.
Your new code puts a module filled in with the names of the database columns (and not the actual data) in the ArrayList:
from.add(new Module(NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_DEVICETYPE, NotesDbAdapter.KEY_HOMECODE, NotesDbAdapter.KEY_DEVICECODE));
Then your custom adapter works correctly, because it displays those values.
What probably got you confused is that you were passing the same strings to the SimpleCursorAdapter, but that adapter uses the column names to fetch data from the database. Your custom adapter instead simply shows what's in the list.
If you want to show the values from the database you should stick to SimpleCursorAdapter (or extend it if you need to do more).