ListView with subitems. (Android) - android

I need to show in a listview a query result to the DB. I'm returning the query 2 values ​​("cod", "value"). I thought of using a SimpleAdapter to solve the problem, but it did not work.
this is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.techcharacteristic);
PopulateTechCharacteristicList populateList = new PopulateTechCharacteristicList(
this);
populateList.execute();
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.techcharacteristic_rows,
new String[] {"cod", "value"}, new int[] {
R.id.techCharacteristic, R.id.techCharacteristicName });
setListAdapter(adapter);
}
public class PopulateTechCharacteristicList extends
AsyncTask<Integer, String, Integer> {
ProgressDialog progress;
Context context;
public PopulateTechCharacteristicList(Context context) {
this.context = context;
}
protected void onPreExecute() {
progress = ProgressDialog.show(TechCharacteristicList.this,
getResources().getString(R.string.Wait), getResources()
.getString(R.string.LoadingOperations));
}
protected Integer doInBackground(Integer... paramss) {
ArrayList<TechCharacteristic> arrayTechChar = new ArrayList<TechCharacteristic>();
TechCharacteristicWSQueries techCharWSQueries = new TechCharacteristicWSQueries();
try {
arrayTechChar = techCharWSQueries
.selectTechCharacteristicByAsset("ARCH-0026");
HashMap<String, String> temp = new HashMap<String,
for(TechCharacteristic strAux : arrayTechChar)
{
temp.put("cod", strAux.getTechCharacteristic() + " - " + strAux.getTechCharacteristicName());
temp.put("value", strAux.getTechCharacteristicValue());
list.add(temp);
}
} catch (QueryException e) {
e.printStackTrace();
return 0;
}
return 1;
}
protected void onPostExecute(Integer result) {
if(result == 1)
progress.dismiss();
}
}
On account of being utlizando the same codes ("cod", "value") to include values ​​in the HashMap, my listView is always showing the last item inserted. But in my statement SimpleAdapter'm using hard coded ("cod", "value") and whenever I put any value other than ("cod", "value") in the HashMap, the listView carries empty.
Can anyone help me?

On account of being utlizando the same codes ("cod", "value") to
include values ​​in the HashMap, my listView is always showing the
last item inserted.
As you are creating HashMap object out of for loop, and adding values to that object only in the for loop,hence the previous values get erased and you get only last values.
To solve this you need to create the HashMap object in for loop corresponding to each row.
Try
HashMap<String, String> temp = null;
for(TechCharacteristic strAux : arrayTechChar)
{
temp = new HashMap<String,String>();
temp.put("cod", strAux.getTechCharacteristic() + " - " + strAux.getTechCharacteristicName());
temp.put("value", strAux.getTechCharacteristicValue());
list.add(temp);
}

Related

Android - asynctask execution order

I have a problem with AsyncTask, onPostExecute method runs before doInBackground method finishes its job.
I'm trying to get some data from Firebase database, save it to an array list of "Didattica" objects to be passed to an expandable list view, I have 4 object on the database.
The problem is that onPostExecute runs soon after doInBackground and then doInBackground finishes its job populating the arrayList.
public class DidatticaActivity extends AppCompatActivity {
ArrayList<Didattica> reishiki1 = null;
private ExpandableListView listView1;
private ExpandableListAdapter listAdapter1;
private List<String> listDataHeader1;
private HashMap<String, List<String>> listHash1;
AsyncTaskDidattica atDidattica;
final FirebaseDatabase database = FirebaseDatabase.getInstance();
private DatabaseReference refDidattica1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_didattica);
listHash1 = new HashMap<>();
listDataHeader1 = new ArrayList<>();
listView1 = findViewById(R.id.lvReishiki);
atDidattica = new AsyncTaskDidattica();
atDidattica.execute();
listAdapter1 = new ExpandableListAdapter(this, listDataHeader1,listHash1);
listView1.setAdapter(listAdapter1);
}
private class AsyncTaskDidattica extends AsyncTask<String, String, HashMap<String, ArrayList<Didattica>>>{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected HashMap<String, ArrayList<Didattica>> doInBackground(String... strings) {
HashMap result = new HashMap<>();
reishiki1 = new ArrayList<>();
try {
refDidattica1 = database.getReference("didattica/1-reishiki");
refDidattica1.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot1) {
Log.i("shinseiLog", "onDataChange" );
for (DataSnapshot child1 : dataSnapshot1.getChildren()) {
Didattica d1 = child1.getValue(Didattica.class);
reishiki1.add(d1);
}
Log.i("shinseiLog", "rei size1: " + reishiki1.size());
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
result.put("reishiki", reishiki1);
Log.i("shinseiLog", "map size 1: " + result.size());
return result;
}catch(Exception e){
Log.i("shinseiLog", "eccezione in doInBackground");
}
return null;
}
#Override
protected void onPostExecute(HashMap<String, ArrayList<Didattica>> result) {
super.onPostExecute(result);
ArrayList<Didattica> rei = result.get("reishiki");
Log.i("shinseiLog", "rei size2: " + rei.size());
for(Didattica r: rei){
listDataHeader1.add(r.getTitolo());
listHash1.put(r.getTitolo(),r.getList());
}
Log.i("shinseiLog", "header: " + listDataHeader1.size());
Log.i("shinseiLog", "hash: " + listHash1.size());
listAdapter1.notifyDataSetChanged();
}
}
}
I added some logs to help understand the order:
I/shinseiLog: map size 1: 1
I/shinseiLog: rei size2: 0
I/shinseiLog: header: 0
I/shinseiLog: hash: 0
I/shinseiLog: onDataChange
I/shinseiLog: rei size1: 4
Last row correctly shows that the arrayList contains all my data, but it is too late.
Why is it executing this way? Where am I wrong?
Thanks
Remember that firebase is async.
So your method...
public void onDataChange(DataSnapshot dataSnapshot1) {
}
...is executing in another thread. That's why onPostExecute is executed first.
Try this, put the code from onPostexecute code inside the method onDataChange, see this picture
Firebase is already Asynchronous, you dont need to use an AsyncTask to get or upload data.

Force Close App when display data into listview using asynctask

when i run applicatiom was force close. this application function is display data from sqlite in listview by using asynctask. but i get error in nullpointer at
collegeList.add(map); --> nullpointer
Then, i want is, data will display by id. the id is foreign key.
this my code:
private class GetHttpResponse extends AsyncTask<Void, Void, Void> {
ArrayList<HashMap<String, String>> collegeList;
protected void onPreExecute()
{ super.onPreExecute();}
protected Void doInBackground(Void... arg0) {
List<Rainday> raindaydetail = new LinkedList<Rainday>();
raindaydetail=dbHelper.getAllRainday();
for(Rainday temp_vg: raindaydetail){
temp_vg.getId();
temp_vg.getYear_rainday();
temp_vg.getJan();
temp_vg.getFeb();
temp_vg.getMar();
temp_vg.getApr();
temp_vg.getMay();
temp_vg.getJun();
temp_vg.getJul();
temp_vg.getAug();
temp_vg.getSep();
temp_vg.getOct();
temp_vg.getNov();
temp_vg.getDec();
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put("id", String.valueOf(temp_vg.getId()));
map.put("year_rainfall", temp_vg.getYear_rainday());
map.put("jan", temp_vg.getJan());
map.put("feb", temp_vg.getFeb());
map.put("mar", temp_vg.getMar());
map.put("apr", temp_vg.getApr());
map.put("may", temp_vg.getMay());
map.put("jun", temp_vg.getJun());
map.put("jul", temp_vg.getJul());
map.put("aug", temp_vg.getAug());
map.put("sep", temp_vg.getSep());
map.put("oct", temp_vg.getOct());
map.put("nov", temp_vg.getNov());
map.put("dec", temp_vg.getDec());
collegeList.add(map);
}
return null;
}
protected void onPostExecute(Void result)
{
proCollageList.setVisibility(View.GONE);
listCollege.setVisibility(View.VISIBLE);
if (collegeList != null) {
ListAdapterRainday adapter = new ListAdapterRainday(RaindayReport.this, collegeList);
listCollege.setAdapter(adapter);}}
MySQLiteHelper :
public List<Rainday> getAllRainday() {
List<Rainday> rainday = new LinkedList<Rainday>();
// 1. build the query
String query = "SELECT * FROM " + TABLE_RAINDAY + " WHERE id = " + KEY_ID_RAINDAY;
// 2. get reference to writable DB
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.rawQuery(query, null);
// 3. go over each row, build book and add it to list
Rainday rainday1 = null;
if (cursor.moveToFirst()) {
do {
rainday1 = new Rainday();
rainday1.setId(Integer.parseInt(cursor.getString(0)));
rainday1.setYear_rainday(cursor.getString(1));
rainday1.setJan(cursor.getString(2));
rainday1.setFeb(cursor.getString(3));
rainday1.setMar(cursor.getString(4));
rainday1.setApr(cursor.getString(5));
rainday1.setMay(cursor.getString(6));
rainday1.setJun(cursor.getString(7));
rainday1.setJul(cursor.getString(8));
rainday1.setAug(cursor.getString(9));
rainday1.setSep(cursor.getString(10));
rainday1.setOct(cursor.getString(11));
rainday1.setNov(cursor.getString(12));
rainday1.setDec(cursor.getString(13));
// Add vgm
rainday.add(rainday1);
} while (cursor.moveToNext());
}
return rainday;
}
i need your help. if anybody helped me, i will appreciate it.
i think you forgot to initialize your collegeList
just initialize it like this
ArrayList<HashMap<String, String>> collegeList;
collegeList= new ArrayList<>();
In your code I found below line
ArrayList<HashMap<String, String>> collegeList;
And you are not initializing collegeList any where in your code

error when try to fill list view adapter on asynctask

this is a pice of my code and i use async task to search from database and fill the listview using simple adapter.
protected String doInBackground(String... arg0)
{
Cursor TROWS;
ArrayList<HashMap<String, String>> LstViw_VItem=new ArrayList<HashMap<String,String>>();
HashMap<String, String>VMap;
try
{
DBH.openDataBase();
SQLiteDatabase SQLITE=SQLiteDatabase.openDatabase(myPath, null, Context.MODE_PRIVATE);
if (TxtVerminSearch.getText().length()==0)
{
TROWS=SQLITE.rawQuery("select id,vermin_name from pistachio_vermins", null);
}
else
{
TROWS=SQLITE.rawQuery("select id,vermin_name from pistachio_vermins where vermin_name like '%"+TxtVerminSearch.getText()+"%'", null);
}
if (TROWS.moveToFirst())
{
do
{
String VID =TROWS.getString(0);
String VName =TROWS.getString(1);
VMap=new HashMap<String, String>();
VMap.put("VerminID", VID);
VMap.put("VerminName", VName);
LstViw_VItem.add(VMap);
}
while (TROWS.moveToNext());
SimpleAdapter SA=new SimpleAdapter(getApplicationContext(), LstViw_VItem, R.layout.xvermin_items, new String[]{"VerminID","VerminName"}, new int[]{R.id.mainmenu_items__lbl_vermin_id,R.id.mainmenu_items__lbl_vermins});
LstViwVerminItems.setAdapter(SA);
LstViwVerminItems.setEnabled(true);
}
else
{
VMap=new HashMap<String, String>();
VMap.put("VerminID", "-1");
VMap.put("VerminName", "nothing found");
VMap.put("ImgViw",String.valueOf(R.drawable.warning_48));
LstViw_VItem.add(VMap);
SimpleAdapter SA=new SimpleAdapter(getApplicationContext(), LstViw_VItem, R.layout.xvermin_items, new String[]{"VerminID","VerminName","ImgViw"}, new int[]{R.id.mainmenu_items__lbl_vermin_id,R.id.mainmenu_items__lbl_vermins,R.id.mainmenu_items__ImgViw});
LstViwVerminItems.setAdapter(SA);
LstViwVerminItems.setEnabled(false);
}
}
catch (Exception e)
{
final String errString;
errString=e.getMessage();
Log.d("ERR: ", errString);
runOnUiThread(new Runnable()
{
public void run()
{
Toast.makeText(JAct_Vermins.this, errString, Toast.LENGTH_LONG).show();
}
});
}
return null;
}
every thing work fine but when result of search is empty i give an error like this:
Only the original thread that created a view hierarchy can touch its views.
and the problem happen on the this line
VMap.put("ImgViw",String.valueOf(R.drawable.warning_48));
befor of this, i use runOnUiThread function to access ui. but i can not do it right now because i can not declare VMap as final
try to declare HashMap<String, String> VMap; outside doInBackgound() and use runOnUiThread(). If it still doesn't work, try to create a Handler and pass your hashmap key-val as Message.
Note: Declare your VMap variable outside doInBackground()
example:
HashMap<String, String> VMap;
#Override
protected String doInBackground(String... params) {
Cursor TROWS;
ArrayList<HashMap<String, String>> LstViw_VItem = new ArrayList<HashMap<String, String>>();
try {
DBH.openDataBase();
SQLiteDatabase SQLITE = SQLiteDatabase.openDatabase(myPath, null,
Context.MODE_PRIVATE);
if (TxtVerminSearch.getText().length() == 0) {
TROWS = SQLITE.rawQuery("select id,vermin_name from pistachio_vermins", null);
} else {
TROWS = SQLITE.rawQuery(
"select id,vermin_name from pistachio_vermins where vermin_name like '%"
+ TxtVerminSearch.getText() + "%'", null);
}
if (TROWS.moveToFirst()) {
do {
String VID = TROWS.getString(0);
String VName = TROWS.getString(1);
VMap = new HashMap<String, String>();
VMap.put("VerminID", VID);
VMap.put("VerminName", VName);
LstViw_VItem.add(VMap);
} while (TROWS.moveToNext());
SimpleAdapter SA = new SimpleAdapter(getApplicationContext(), LstViw_VItem,
R.layout.xvermin_items, new String[] { "VerminID", "VerminName" },
new int[] { R.id.mainmenu_items__lbl_vermin_id,
R.id.mainmenu_items__lbl_vermins });
LstViwVerminItems.setAdapter(SA);
LstViwVerminItems.setEnabled(true);
} else {
VMap = new HashMap<String, String>();
VMap.put("VerminID", "-1");
VMap.put("VerminName", "nothing found");
mHandler.sendEmptyMessage(0);
LstViw_VItem.add(VMap);
SimpleAdapter SA = new SimpleAdapter(getApplicationContext(), LstViw_VItem,
R.layout.xvermin_items, new String[] { "VerminID", "VerminName",
"ImgViw" }, new int[] { R.id.mainmenu_items__lbl_vermin_id,
R.id.mainmenu_items__lbl_vermins, R.id.mainmenu_items__ImgViw });
LstViwVerminItems.setAdapter(SA);
LstViwVerminItems.setEnabled(false);
}
} catch (Exception e) {
final String errString;
errString = e.getMessage();
Log.d("ERR: ", errString);
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(JAct_Vermins.this, errString, Toast.LENGTH_LONG).show();
}
});
}
return null;
}
private Handler mHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
VMap.put("ImgViw", String.valueOf(R.drawable.warning_48));
super.handleMessage(msg);
}
};
Hope it helps!
You should use the method onPostExecute to show the result at your UI. Learn more about AsyncTask. You shouldn't handle with UI at the doInBackground method.
You are trying to update listview from background which is wrong.
For updating ui android provide post execute method , you should write code for updating listview in postexecute method. For your reference you can see this link http://www.compiletimeerror.com/2013/01/why-and-how-to-use-asynctask.html
function doInBackgound() - cannot call function from ui tread
use runOnUiThread() or onPostExecute()

Search result displayed twice in list view

I would like to display the data from MySql in a listview using a search parameter in my application.
I've succeeded, but the problem I'm having is that every time I push the search button twice, both sets of result data are shown in the ListView, whereas I only want to display the latest set of results.
This is the code I'm using:
public class ListPerusahaan extends ListActivity {
/** Called when the activity is first created. */
private static final String TAG_ID = "id";
private static final String TAG_NAMA = "nama_perusahaan";
private static final String TAG_PEKERJAAN = "pekerjaan";
private static final String TAG_ALAMAT= "alamat";
private static final String TAG_DEADLINE = "deadline";
EditText keyword; Button search; private ProgressDialog pDialog; ArrayList<HashMap<String, String>> DataList; // JSONArray perusahaan = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listperusahaan);
keyword=(EditText)findViewById(R.id.Editsearch);
search=(Button)findViewById(R.id.search);
DataList = new ArrayList<HashMap<String, String>>();
search.setOnClickListener(new View.OnClickListener()
{
#Override public void onClick(View v) {
// TODO Auto-generated method stub
if (keyword.getText().toString().length() == 0 ) {
Toast toast = Toast.makeText(getApplicationContext(),"Please enter your keyword", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
else {
new searchData().execute();
}
}
});
}
#SuppressLint("NewApi") public class searchData extends AsyncTask<Void, Void, Void>
{
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(ListPerusahaan.this);
pDialog.setMessage("Loading ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();
List<NameValuePair> paramemeter = new ArrayList<NameValuePair>();
paramemeter.add(new BasicNameValuePair("keyword", keyword.getText().toString()));
JSONObject json = JSONParser.getJSONFromUrl("http://10.0.2.2/appmysql/dataperusahaan.php", paramemeter);
try{
JSONArray perusahaan = json.getJSONArray("perusahaan");
if (perusahaan != null)
{
for(int i=0;i<perusahaan.length();i++){
// HashMap<String, String> map1 = new HashMap<String, String>();
JSONObject jsonobj = perusahaan.getJSONObject(i);
// Storing each json item in variable
String id = jsonobj.getString(TAG_ID);
String nama_perusahaan = jsonobj.getString(TAG_NAMA);
String pekerjaan = jsonobj.getString(TAG_PEKERJAAN);
String alamat = jsonobj.getString(TAG_ALAMAT);
String deadline = jsonobj.getString(TAG_DEADLINE);
// creating new HashMap
HashMap<String, String> map1 = new HashMap<String, String>();
// adding each child node to HashMap key => value
map1.put(TAG_ID, id);
map1.put(TAG_NAMA, nama_perusahaan);
map1.put(TAG_PEKERJAAN, pekerjaan);
map1.put(TAG_ALAMAT, alamat);
map1.put(TAG_DEADLINE, deadline);
// adding HashList to ArrayList
DataList.add(map1);
}
}
else {
Toast toast= Toast.makeText(getApplicationContext(), "No data found", Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0);
toast.show();
}
}
catch(JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into ListView
* */
ListAdapter adapter = new SimpleAdapter(
ListPerusahaan.this, DataList,R.layout.row,
new String[] { TAG_NAMA, TAG_PEKERJAAN, TAG_ALAMAT, TAG_DEADLINE },
new int[] { R.id.nama_perusahaan, R.id.pekerjaan, R.id.alamat,R.id.deadline});
// updating listview
setListAdapter(adapter);
final ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
/*
#SuppressWarnings("unchecked")
HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(position);
Toast.makeText(ListPerusahaan.this, "Perusahaan '" + o.get("nama_perusahaan") + "' was clicked.", Toast.LENGTH_SHORT).show();
*/
// getting values from selected ListItem
String nama = ((TextView) view.findViewById(R.id.nama_perusahaan)).getText().toString();
String pekerjaan = ((TextView) view.findViewById(R.id.pekerjaan)).getText().toString();
String alamat = ((TextView) view.findViewById(R.id.alamat)).getText().toString();
String deadline = ((TextView) view.findViewById(R.id.deadline)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), detail_lowongan.class);
in.putExtra(TAG_NAMA, nama);
in.putExtra(TAG_PEKERJAAN, pekerjaan);
in.putExtra(TAG_ALAMAT, alamat);
in.putExtra(TAG_DEADLINE, deadline);
startActivity(in);
}
});
}
});
}
}
}
Edit: in onclick clear DataList
search.setOnClickListener(){
......
DataList.clear(); //in onclick method
}
I am not sure whether you are looking for this or not...but if you don't want to allow duplicates in your list try ....
When the data filled in your list
Set<type> set=new Hashset(yourlist);
ArrayList<type> nodupList=new ArrayList<type>();
noduplist.addAll(set);
using this way it will remove the duplicates in your list
Edit:
Try this
After for loop
Set<HashMap> set=new HashSet(DataList);
ArrayList<HashMap> nodupList=new ArrayList<HashMap>();
nodupList.addAll(set);
DataList.clear();
DataList.addAll(nodupList);
try it may help you
Clear the DataList of the ArrayList type before populating it in the for loop.

Clear ListView Items and Refresh it in Android

I use internet service to fill a list view. I want to refresh the list view items when user press the refresh button. how can i do this?
In AsyncTask and postExecute i fill the list view:
protected void onPostExecute(String file_url) {
pDialog.dismiss();
try {
if (jSon.has(KEY_SUCCESS)) {
String success = jSon.getString(KEY_SUCCESS);
if (success.equals("1")) {
notes = jSon.getJSONObject("notes");
for (int i = 0; i < notes.length(); i++) {
JSONObject c = notes.getJSONObject(Integer
.toString(i));
Log.i("JSONObject c >>", c.toString());
String id = c.getString(KEY_NOTE_ID);
String subject = c.getString(KEY_NOTE_SUBJECT);
String date = c.getString(KEY_NOTE_DATE);
HashMap<String, String> map = new HashMap<String, String>();
map.put(KEY_NOTE_ID, id);
map.put(KEY_NOTE_SUBJECT, subject);
map.put(KEY_NOTE_DATE, date);
noteList.add(map);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
runOnUiThread(new Runnable() {
public void run() {
ListAdapter adapter = new SimpleAdapter(AllNotes.this,
noteList, R.layout.list_item, new String[] {
KEY_NOTE_ID, KEY_NOTE_SUBJECT,
KEY_NOTE_DATE }, new int[] {
R.id.list_lbl_id, R.id.list_lbl_subject,
R.id.list_lbl_date });
setListAdapter(adapter);
}
});
}
The most basic approach is to empty noteList and run your AsyncTask again.
Inside onPreExecute() (or the first line of doInBackground()) call either:
noteList = new ArrayList<Map<String, String>>(); // or noteList.clear();
Call your AsyncTask's execute() method again.
Also I don't believe you need to use runOnUiThread() in onPostExecute() because it already has access to the main thread.

Categories

Resources