Remove or Clear content in SimpleAdapter in Android? - java

Here is the code:
ibtSearchStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
try{
searchQuery = etSearchThis.getText().toString();
searchQuery = searchQuery.toUpperCase();
cursor = searchActivity.getData(product, "product", tableColumns);
//Clean ArrayList
resultRow.clear();
resultTable.clear();
//Get Search Result
resultTable = searchActivity.searchByProductName(cursor, searchQuery);
//Display Search Result
for(int ctr = 0; ctr < resultTable.size(); ctr++){
HashMap<String, String> map = new HashMap<String, String>();
resultRow = resultTable.get(ctr);
String result = resultRow.get(2);
map.put("ProductName",result);
list.add(map);
}
Log.e("resultProduct", "" + list);
adapter = new SimpleAdapter(
SearchMain.this,
list,
R.layout.search_result,
new String[]{"ProductName"},
new int[]{R.id.tvProductName}
);
lvSearchResult.setAdapter(adapter);
}
finally{
product.close();
}
}
});
The function of this is that it will search for a match in the database then it will insert the result of the search in a HashMap then on a adapter.
But every click i am not able to remove the previous result.
What is the proper implementation to this?

When you are working with adapters and the information changes, be sure that you are calling adapter.notifyDataSetChanged();

You set a new adapter each time the OnClick event is triggered. As Jay Snayder wrote you should use adapter.notifyDataSetChanged(); instead. But be sure to set the adapter only once and move the following part of your code (e.g. to your onCreate() method of the activity):
adapter = new SimpleAdapter(
SearchMain.this,
list,
R.layout.search_result,
new String[]{"ProductName"},
new int[]{R.id.tvProductName}
);
lvSearchResult.setAdapter(adapter);
Just update the DataSet of your adapter (here: 'list').

Related

ArrayAdapter crashes when adding new items to adapter

I am facing a problem that when I try to dynamically add items to my spinner the app crashes. So first I add an array from Strings.xml my R.array.restrictions contains 16 items therefore I am inserting each key into 16 and then adding it onto the next position. and after that I load each item from firebase and add it to the adapter, then I set the adapter, so in my mind it should work. Any ideas why it causes a crash? Says:
UnsupportedOperationException at
java.util.AbstractList.add(AbstractList.java:148)
Thanks.
public void startSpinner(){
//built in Profiles
spinner = (Spinner) findViewById(R.id.spinnerProfiles);
adapter = ArrayAdapter.createFromResource(this, R.array.restrictions, android.R.layout.simple_spinner_item);
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
map = (Map<String, Object>) dataSnapshot.child("users").child(userID).getValue();
ArrayList<String> array = new ArrayList<>();
int x = 16;
for (Map.Entry<String,Object> entry : map.entrySet()) {
// key contains Profile Name
String key = entry.getKey();
adapter.insert(key, x);
x++;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//Auto Generated Method
}
});
adapter.setDropDownViewResource(android.R.layout.simple_list_item_1);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
}
Perhaps the problem is that you are changing an array that is coming from resources. This can happen as the list you are using is not created by you.
You can try the following:
ArrayList<CharSequence> array = new ArrayList<CharSequence>(Arrays.asList(context.getResources().getTextArray(R.array.restrictions)));
adapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, array);

Populate a ListView with Keysets

I am new to Android and Java but I have been trying to do this for a while now and have some ideas to how this may work, but I don't know how to put it in code.
I have two Activities, one that is a Log and one that creates a new log. Basically, when a user makes a new log and saves it, it is saved as a keyset with the key being the Log Name.
I then want to take the newly created Log entry and add it to my list on another Activity.
I can only seem to populate the first item in the list with all the KeySets instead of them being listed one by one by adding as a new item.
The code I need is just to populate each item in the ListView as one of the Keys in the KeySets and when the user clicks it loads the values.
The code I have from ActivityLog:
public void loadLog (View view){
SharedPreferences userInfo = getSharedPreferences("userData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = userInfo.edit();
String myString = userInfo.getAll().keySet().toString();
String[] values = new String[] { myString
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.activity_list_item, android.R.id.text1 );
Map<String, ?> allEntries = userInfo.getAll();
for (Map.Entry<String, ?> entry : allEntries.entrySet()) {
Log.d("map values", entry.getKey() + ": " + entry.getValue().toString());
listView.setAdapter(adapter);
}}
Code for ActivityNewLog:
public void saveLog (View view){
EditText Date = (EditText)findViewById(R.id.editDate);
EditText Name = (EditText)findViewById(R.id.editName);
EditText Cal = (EditText)findViewById(R.id.editCal);
EditText STime = (EditText)findViewById(R.id.editSTime);
EditText ETime = (EditText)findViewById(R.id.editETime);
EditText Entry = (EditText)findViewById(R.id.editEntry);
try {
SharedPreferences userInfo = getSharedPreferences("userData", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = userInfo.edit();
Set<String> LogSet = new HashSet<String>();
LogSet.add(Date.getText().toString());
LogSet.add(Name.getText().toString());
LogSet.add(Cal.getText().toString());
LogSet.add(STime.getText().toString());
LogSet.add(ETime.getText().toString());
editor.putStringSet( Entry.getText().toString(), LogSet);
editor.commit();
Context context = getApplicationContext();
CharSequence text = "User data saved!";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
catch(Exception ex) {
// insert your own error message here
}
}
I would appreciate any help or advice to improve this code.
I would recommend you use a SQLite database instead, but here you put a key into the SharedPreferences / HashMap.
editor.putStringSet( Entry.getText().toString(), LogSet);
Now, you have to get that value back out...
Map<String, ?> allEntries = userInfo.getAll();
Set<String> entry = allEntries.get("<some value here>"); // <-- Whatever you put in
And when you have that, you can loop over them to add to the adapter.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.activity_list_item, android.R.id.text1 );
listView.setAdapter(adapter);
for (String s : entry) {
adapter.add(s);
}

RecyclierView's notifyItemInserted does not work with arrayList

I have 1 ArrayList and 1 RecyclerView. Data from DB are retrieved and stored in the ArrayList for displaying in the RecyclerView. All the things work fine with adding new item to the RecyclerView, but without the adding animation. I know I should use notifyItemInserted for the adding animation, but it didn't work. No inserting animation was appearing. Now I have to go back to the previous page and then get in the page again so that the added item was showing. So, how to add back the inserting animation?
Any help will be very much appreciated. Thanks.
Code to pass the data and set the adapter:
db = new DatabaseHelper(this);
dbList = new ArrayList<>();
dbList = db.getFilteredItems();
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
//newest to oldest order (database stores from oldest to newest)
llm.setReverseLayout(true);
llm.setStackFromEnd(true);
mRecyclerView.setLayoutManager(llm);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
adapter = new RecyclerAdapter(this, llm, dbList);
mRecyclerView.setAdapter(adapter);
Code to retrieve data from DB:
//retrieve filtered data from DB
public List<AudioItem> getFilteredItems(){
List<AudioItem> audioList = new ArrayList<>();
String titleName = EditActivity.titleName;
String query = "select * from " + TABLE_NAME + " where " + COLUMN_NAME_RECORDING_NAME + " like '" + titleName + "%'";
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query,null);
if (cursor.moveToFirst()){
do {
AudioItem audio = new AudioItem();
audio.setId(Integer.parseInt(cursor.getString(0)));
audio.setName(cursor.getString(1));
audio.setFilePath(cursor.getString(2));
audio.setLength(Integer.parseInt(cursor.getString(3)));
audio.setTime(Long.parseLong(cursor.getString(4)));
audioList.add(audio);
}while (cursor.moveToNext());
cursor.close();
}
return audioList;
}
Code to insert data into the DB:
/* Insert data into database */
public void addRecording(String recordingName, String filePath, long length) {
SQLiteDatabase db = getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COLUMN_NAME_RECORDING_NAME, recordingName);
cv.put(COLUMN_NAME_RECORDING_FILE_PATH, filePath);
cv.put(COLUMN_NAME_RECORDING_LENGTH, length);
cv.put(COLUMN_NAME_TIME_ADDED, System.currentTimeMillis());
db.insert(TABLE_NAME, null, cv);
db.close();
if (mOnDatabaseChangedListener != null) {
mOnDatabaseChangedListener.onNewDatabaseEntryAdded();
}
}
Code to invoke the inserting animation:
#Override
public void onNewDatabaseEntryAdded() {
//item added to top of the list
Log.e("Count: ", Integer.toString(getItemCount()));
// notifyDataSetChanged();
notifyItemInserted(getItemCount());
//llm.scrollToPosition(getItemCount() - 1);
}
If you make a new ArrayList every time something changes and assign it to a new adapter and assign that new adapter to the RecyclerView, wonky things happen.
You should break the ArrayLists out into a Model type of object or integrate them into your current DB model object. If you do this, you can simply update itemlist and the changes will be reflected in your RecyclerView.
Here's some pseudo code since I don't really have much of your code to work off of:
public class DataModel {
private ArrayList<Foo> itemlist = new ArrayList<>();
public DataModel(){}
public ArrayList<Foo> getItemList() { return itemlist; }
}
public class YourActivity extends Activity {
private DataModel data = new DataModel();
#Override
protected void onCreate(Bundle b) {
if (b == null) {
RecyclerView dataView = (RecyclerView) findViewById(R.id.recyclerView);
dataView.setAdapter(new RecyclerAdapter(this, new LinearLayoutManager(this), data.getItemList()));
}
}
}
After you set things up this way, whenever you update itemlist, you should be seeing the changes automatically reflected. If not, call notifyDataSetChanged().

Java.Lang.NullPointerException while using listview simple adapter

I have a listview that shows two sqlite tables' values. First I tried to use ArrayAdapter to view them and all values were shown. But they looked messy, so I tried using a simple adapter. hHre is my code.
for(int i=0; i<= promo.size();i++){
ProductModulePromo b =dataSource.getproductmodulepromo(moduleid);
productmoduledesc = b.getProductmoduledesc().toString();
producttype = b.getProducttype().toString();
productpromo = b.getproductpromotion().toString();
map1.put("three",productpromo);
map1.put("two",producttype);
map1.put("one",productmoduledesc);
Globals.promo.add(map1);}
promo is my arraylist<productmodulepromo>(). when i try to compile those code. all values that shown are same. so i try to change with this code on datasource.java and use those arraylist on formpromo.java. here is my DBDatasource.java's code:
public ArrayList<HashMap<String, String>> getproduct1() {
ArrayList<HashMap<String, String>> promo = new ArrayList<HashMap<String, String>>();
database = dbHelper.getReadableDatabase();
Cursor cursor = database.rawQuery("select productmodule.productmoduledescription, productdetail.producttype, productdetail.productpromotion from productmodule, productdetail where productmodule.productmoduleid=productdetail.productmoduleid", null);
cursor.moveToFirst();
if (cursor.moveToFirst()) {
do {
productmoduledesc=cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_MODULE_DESC));
producttype = cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_TYPE));
productpromo = cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_PROMOTION));
map1.put("one",productmoduledesc);
map1.put("two",producttype);
map1.put("three",productpromo);
promo.add(map1);
} while (cursor.moveToNext());
}
cursor.close();
return promo;
}
here is my Formpromo.java :
dataSource = new DBDataSource(this);
dataSource.open();
promo = dataSource.getproduct1();
adapter = new SimpleAdapter(FormPromo.this, promo, R.layout.item_to,
new String[] {"one","two","three"},
new int[] {R.id.edtbrandto,R.id.edtqtyto,R.id.edtharga});
setListAdapter(adapter);
final ListView listpromo = (ListView) findViewById(android.R.id.list);
setListAdapter(adapter);
and I am getting an error as Java.Lang.NullpointerException on map1.put("one",productmoduledesc);. I have no idea how to fix them all. Thanks for help. any help will be appreciated.
Seems like you never set map1, add it to the beginning of the loop, because else you'd overwrite the old values
like this
...
do {
map1 = newHashMap<String, String>(); // add
productmoduledesc=cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_MODULE_DESC));
producttype = cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_TYPE));
productpromo = cursor.getString(cursor.getColumnIndex(DBHelper.PRODUCT_PROMOTION));
map1.put("one",productmoduledesc);
map1.put("two",producttype);
map1.put("three",productpromo);
promo.add(map1);
} while (cursor.moveToNext());
...

How to update the Arraylist every second in onNewIntent and in Android 4.3?

I am developing an application where I have to connect to Bluetooth device on Android 4.3.
I want to update the Arraylist every second.
And in my application. The DeviceControl.java will transmit the parameter by using intent and startActivity.
The Main.java will receive the parameter from DeviceControl.java and put in to Arraylist like the dollowing code.
Main.java
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
onNewIntent(getIntent());
}
#Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
setIntent(intent);
for(int i = 0;i<5;i++)
{
if(address[i].length() != 1) {
HashMap<String, Object> item = new HashMap<String, Object>();
item.put("name", name[i]);
item.put("address", address[i]);
item.put("RSSI", rssi[i]);
item.put("Battery", battery[i]);
list.add(item);
mdeviceAddress = address[i];
} else if(address[i].length() == 1)
break;
}
mHandler.postDelayed(addlist, 1000); //update the list
adapter = new SimpleAdapter(this, list, R.layout.device_list_name_address,
new String[] {"name", "address", "RSSI", "Battery"},
new int[] {R.id.device_name, R.id.device_address, R.id.device_rssi, R.id.device_battery} );
devicelist.setAdapter(adapter);
}
But it only update the list once time when the DeviceControl.java launch the intent.
I want it always update the list after DeviceControl.java launch the intent.
I have try to type the code of Arraylist in Runnable, but it doesn't work.
What should I do to make the Arraylist auto update ??
EDIT
I add the code of runnable of the following
final Runnable addlist = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<5;i++)
{
if(address[i].length() != 1){
ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String,Object>>();
HashMap<String, Object> item = new HashMap<String, Object>();
item.put("name", name[i]);
item.put("address", address[i]);
item.put("RSSI", "11111:" + rssi[i]);
item.put("Battery", "22222:" + battery[i]);
list.add(item);
Log.v(TAG, "onNewIntent----------------------------");
mdeviceAddress = address[i];
Log.v(TAG, "address[" + i + "] = " + address[i]);
Log.v(TAG, "GATT[" + i + "] = " + gatt[i]);
//並連線到此Address
Intent gattServiceIntent = new Intent(Main.this, BluetoothLeService.class);
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}else if(address[i].length() == 1)
break;
}
adapter.notifyDataSetChanged();
mHandler.postDelayed(this, 1500);
}
};
And type the mHandler.postDelayed(addlist, 1000); in OnNewIntent after for loop. The list should should be change from
item.put("RSSI", rssi[i]);
item.put("Battery", battery[i]);
to
item.put("RSSI", "11111:" + rssi[i]);
item.put("Battery", "22222:" + battery[i]);
But it didn't change anything.
Did you make use of notifyDataSetChanged() to update your list?
If not then you can write adapter.notifyDataSetChanged() in runnable. That will update your list. I hope this will help you.
See the demo http://xjaphx.wordpress.com/2011/07/15/listview-in-one-activity-doesnt-refresh-data-sending-another-activity/
I guess notifyDataSetChanged() does not work since the adapter points to the "old list", not the "new list". Don't create a new ArrayList, use the one tied to the adapter.
Try this:
ArrayList<HashMap<String, Object>> tmp = new ArrayList<HashMap<String,Object>>();
//set data
list.clear();
list.addAll(tmp);
Hope that helps.

Categories