I have serious problems with my ListActivity. When I open it and start scrolling, the app freezes for some seconds and after that it can be scrolled smoothly. I don't get an "application not responding" error. I made a *.hprof heap dump and put it into MAT. Here you can see my leaks:
Seems like something is fishy. Maybe I'm not using the cursor in the right way.
Here you can take a look at my code:
public class ListViewActivity extends ListActivity implements OnClickListener {
// Resources
static String like;
// Cursor
private SimpleCursorAdapter adapter;
private Cursor cursor;
String[] showColumns;
int[] showViews;
// Database
private DBAccess dbAccess;
#Override
public void onCreate(Bundle savedInstanceState) {
// Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
ListViewActivity.like = "";
Intent intent = getIntent(); // gets the previously created intent
ListViewActivity.like = intent.getStringExtra("like");
new DatabaseTask().execute(null, null, null);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Cursor item = (Cursor) getListAdapter().getItem(position);
Intent intent = new Intent(ListViewActivity.this, ListClickActivity.class);
intent.putExtra("id", item.getString(0));
startActivity(intent);
}
private class DatabaseTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Log.v("doInBackground", "started!");
dbAccess = new DBAccess(ListViewActivity.this, 1, "FishingMatey.db");
dbAccess.initDownloadedDatabase();
cursor = dbAccess
.createBewirtschafterListViewCursor(ListViewActivity.like);
showColumns = new String[] { "gewName", "reviergrenzen" };
showViews = new int[] { R.id.datensatz_gewName,
R.id.datensatz_reviergrenzen };
Log.v("doInBackground", "finished!");
return null;
}
protected void onPostExecute(Void params) {
adapter = new SimpleCursorAdapter(ListViewActivity.this,
R.layout.datensatz, cursor, showColumns, showViews);
setListAdapter(adapter);
dbAccess.closeDatabase();
Log.v("onPostExecute", "finished!");
}
}
}
EDIT1:
The issue doesn't come from the database because I have the same leak with the following code:
public class ListViewActivity extends ListActivity {
// Activity
public static Activity forFinish;
// Resources
static String like;
// Cursor
private SimpleAdapter adapter;
String[] showColumns;
int[] showViews;
#Override
public void onCreate(Bundle savedInstanceState) {
// Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
forFinish = this;
ListViewActivity.like = "";
Intent intent = getIntent(); // gets the previously created intent
ListViewActivity.like = intent.getStringExtra("like");
// create the grid item mapping
showColumns = new String[] { "gewName", "reviergrenzen" };
showViews = new int[] { R.id.datensatz_gewName,
R.id.datensatz_reviergrenzen };
// prepare the list of all records
List<HashMap<String, String>> fillMaps = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < 20; i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("gewName", "See" + i);
map.put("reviergrenzen", "Revier" + i);
fillMaps.add(map);
}
// fill in the grid_item layout
SimpleAdapter adapter = new SimpleAdapter(this, fillMaps,
R.layout.datensatz, showColumns, showViews);
setListAdapter(adapter);
}
}
Would be awesome if someone can find the memory leak.
Greetings Mike!
If you are using images in your list items then move the image loading to a background task. You could have a look at smoothie, an asynchronous loading list that can be used with Android-BitmapCache for better performance.
Related
I have an android project that gets the values from a remote database. I'm using a listview in eclipse and loops whatever values that my JSON have. Here is my code:
Newsfeed.java
public class NewsFeed extends ListActivity {
// Progress Dialog
private ProgressDialog pDialog;
private static final String READ_COMMENTS_URL = "http://10.0.2.2/PMR_Drupal/newsfeed.php";
private static final String TAG_TITLE = "trans_name";
private static final String TAG_FOR_A = "sub_trans_name";
private static final String TAG_ACCESS_LEVEL = "ACCESS_LEVEL";
private JSONArray mComments = null;
//manages all of our comments in a list.
private ArrayList<HashMap<String, String>> mCommentList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.newsfeed);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_activity_actions, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
//loading the comments via AsyncTask
new LoadComments().execute();
}
public void addComment(View v)
{
Intent i = new Intent("com.pallet.pts.ADDNEWSFEED");
startActivity(i);
}
public void updateJSONdata() {
mCommentList = new ArrayList<HashMap<String, String>>();
JSONParser jParser = new JSONParser();
JSONObject json = jParser.getJSONFromUrl(READ_COMMENTS_URL);
try {
mComments = json.getJSONArray(TAG_POSTS);
for (int i = 0; i < mComments.length(); i++) {
JSONObject c = mComments.getJSONObject(i);
String trans_name = c.getString(TAG_TITLE);
String sub_trans_name = c.getString(TAG_FOR_A);
String ACCESS_LEVEL = c.getString(TAG_ACCESS_LEVEL);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_TITLE, trans_name);
map.put(TAG_FOR_A, sub_trans_name);
map.put(TAG_ACCESS_LEVEL, ACCESS_LEVEL);
mCommentList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
private void updateList() {
ListAdapter adapter = new SimpleAdapter(this, mCommentList,
R.layout.single_post, new String[] { TAG_TITLE, TAG_FOR_A, TAG_ACCESS_LEVEL}, new int[] { R.id.title, R.id.forApproval, R.id.count});
setListAdapter(adapter);
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = new Intent("com.pallet.pts.NEWSFEED_CLICKED");
intent.putExtra("position", position);
startActivity(intent);
}
});
}
public class LoadComments extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(NewsFeed.this);
pDialog.setMessage("Checking for Updates...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
#Override
protected Boolean doInBackground(Void... arg0) {
//we will develop this method in version 2
updateJSONdata();
return null;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
pDialog.dismiss();
//we will develop this method in version 2
updateList();
}
}
}
Now my problem is, since the listview is being looped in, How do I create a listview screen with different content for each row?
Thank you in advance! :D
You need to make an activity which should be blue print for all the activity that will be invoked by ListView .You need to append some values to Intent that you'll be passed to the activity and based on this remaining component can be created dynamically .The way you are doing you will get stuck because the data are coming remote database which may vary time to time.But what I am saying to make a basic skeleton of Activity because most the component will remain same only some of the component may only change which you can add dynamically based on intent valuse
Hello based on the #Shakeeb Shaheen comment here I am trying to write a pseudo-code for you. At first create a xml layout and name it common_layout.xml which will use to show trans and subtrans name. Here is the code of this layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_trans_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv_subtrans_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Create an activity for holding this layout.
Now from the NewsFeed activity you have to pass the trans name and subtrans name value when user click on the each list item. You can do this
Intent intent = new Intent(NewsFeed.this, CommonActivity.class);
intent.putExtra("TRANS_NAME", trans_name);
intent.putExtra("SUBTRANS_NAME", subtrans_name);
startActivity(intent);
And then you have to grab these value in your common activity class. This post also can help you how to pass value between two activity.
I am trying to send row item from list view to another activity but maybe I do something wrong.
I made one app for food.
And I want when the user click to "First Activity" the list item from this listview to be send to "Second Activity" and when the user click to "Add to cart" the listview item go to Cart.class
But when I click to "Add to cart" the Activity is send me tо Cart.class but there have nothing.
In cart.xml I have listvew.
Sorry for my bad english
Thanks in advance.
First Activity.
public class UnderCal extends Activity {
String classes[] = {"Grilled chicken","Asiago","Spicy"};
int[] meal = new int[]{
R.drawable.grilledchicken,
R.drawable.asiago,
R.drawable.spicy
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.under_menu);
final List<HashMap<String,String>> aList = new ArrayList<HashMap<String,String>>();
for(int i=0;i<3;i++){
HashMap<String, String> hm = new HashMap<String,String>();
hm.put("food", Integer.toString(meal[i]));
hm.put("txt", "" + classes[i]);
aList.add(hm);
}
// Keys used in Hashmap
String[] from = {"food","arrow","txt"};
// Ids of views in listview_layout
int[] to = { R.id.food,R.id.arrow,R.id.txt};
// Instantiating an adapter to store each items
// R.layout.listview_layout defines the layout of each item
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), aList, R.layout.list_layout, from, to);
// Getting a reference to listview of main.xml layout file
final ListView listView = ( ListView ) findViewById(R.id.mylist);
// Setting the adapter to the listView
listView.setAdapter(adapter);
listView.setDivider(new ColorDrawable(0xffffffff));
listView.setDividerHeight(1);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
{
if (position == 0)
{
Intent intent = new Intent(UnderCal.this,GrilledChicken.class);
// intent.putExtra("get", aList.get(position));
String result = (String) listView.getItemAtPosition(position).toString();
intent.putExtra("get",result);
startActivity(intent);
overridePendingTransition(R.anim.animation3, R.anim.animation4);
}
}
});
}
Second Activity.
public class GrilledChicken extends Activity {
Button butadd;
//HashMap<String, String> hm;
String list;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.grilled_chicken);
//hash
// hm =(HashMap<String, String>)getIntent().getSerializableExtra("get");
Bundle extras = getIntent().getExtras();
list = extras.getString("get");
butadd=(Button) findViewById(R.id.butadd);
butadd.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(GrilledChicken.this,Cart.class);
// intent.putExtra("hm",hm);
intent.putExtra("list",list);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
}
});
Cart.class
public class Cart extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.cart);
Bundle extras = getIntent().getExtras();
String pos = extras.getInt("list");
}
}
For get item from your listview you have to write following code.
String item = food.get(position).toString();
Write this on your Itemclick method
Put the following code in your Cart.class
Bundle extras = getIntent().getExtras();
String list_data = extras.getString("list");
Now list_data contains the data.
There is another way through which you can do the task also.
Create a separate Global Class
Global.class
public class Globalclass {
public static String list_data;
}
And then in your FirstActivity replace the following
intent.putExtra("get",result);
with
Globalclass.list_data=result;
Now you can access the list_dataanywhere like the following
String data=Globalclass.list_data;
Try this once I hope this will help you.
First of all do this in YourFirstActivity
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(getActivity(), YourSecondActivity.class);
YourModel yourModel = (YourModel) parent.getItemAtPosition(position);
intent.putExtra("yourModel", yourModel);
startActivity(intent);
}
});
At another Activity do this.
YourModel yourModel= (YourModel) getIntent().getSerializableExtra("yourModel");
From yourModel object you will get all the data of your ListView selected item of YourFirstActivity to YourSecondActivity.
Multiple Send ListView Item:-
ArrayList<String>checked11 = new ArrayList<String>();
SparseBooleanArray checked = listView1.getCheckedItemPositions();
final ArrayList<String> selectedItems = new ArrayList<String>();
for (int i = 0; i < checked.size(); i++) {
int position = checked.keyAt(i);
if (checked.get(i))
selectedItems.add(checked11.get(position));
}
String[] outputStrArr = new String[selectedItems.size()];
for (int i = 0; i < selectedItems.size(); i++) {
outputStrArr[i] = selectedItems.get(i);
}
use Bunddle :
Bundle bundle = new Bundle();
Intent intent = new Intent(getApplicationContext(),
OtherActivity.class);
bundle.putStringArray("selectedItems", outputStrArr);
intent.putExtra("screen2", "sub");
intent.putExtras(bundle);
intent.putExtra(EXTRA_RESPONSE, selected);
startActivity(intent);
I have a Listview which pulls and displays data from a sqlite DB. Data in the first column of the DB is displayed in the ListView and when clicked, an Activity starts showing the rest of the column associated with the first column. When the data is edited the ListView needs to be updated to reflect this, but it doesn't show the updates unless the application is restarted.
I've tried calling, notifyDataSetChanged() and startActivityForResult() in my onResume() method but that didn't work. What method should I use to accomplish updating the ListView in my current code?
I understand a SimpleCursorAdapter may be used and I have tried to implement that code with no success. I'm a novice and need actual code to understand what needs to be done.
public class LoginList extends Activity implements OnClickListener, OnItemClickListener {
private ListView loginList;
private Button webLogin;
private ListAdapter loginListAdapter;
private ArrayList<LoginDetails> loginArrayList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)
findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)
findViewById(R.id.button3);
webLogin.setOnClickListener(this);
loginArrayList = new ArrayList<LoginDetails>();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
#Override
public void onClick (View v) {
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
public List<String> populateList () {
List<String> webNameList = new ArrayList<String>();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
sqliteDatabase.close();
return webNameList;
}
#Override
protected void onResume() {
super.onResume();
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, populateList());
loginList.setAdapter(loginListAdapter);
}
#Override
public void onItemClick(AdapterView<?> arg0 , View arg1, int arg2, long arg3) {
Toast.makeText(getApplicationContext(), "Selected ID :" + arg2, Toast.LENGTH_SHORT).show();
Intent updateDeleteLoginInfo = new Intent (this, UpdateDeleteLoginList.class);
LoginDetails clickedObject = loginArrayList.get(arg2);
Bundle loginBundle = new Bundle();
loginBundle.putString("clickedWebSite",clickedObject.getsName());
loginBundle.putString("clickedWebAddress",clickedObject.getwUrl());
loginBundle.putString("clickedUserName",clickedObject.getuName());
loginBundle.putString("clickedPassWord",clickedObject.getpWord());
loginBundle.putString("clickedNotes",clickedObject.getlNotes());
updateDeleteLoginInfo.putExtras(loginBundle);
startActivityForResult(updateDeleteLoginInfo, 0);
}
}
This is exactly what a Loader is great for. I suggest you create a SimpleCursorAdapter to bind the DB to the UI (ListView in this case), a ContentProvider to interface with the DB, and a CursorLoader to monitor the DB for changes, and update the UI when necessary. The Loader will handle all DB changes and update your ListView by simply updating your adapter. It seems like a lot of work up front, but is incredibly powerful once configured, and will work through the entire Android lifecycle.
These tutorials should be helpful:
https://developer.android.com/training/load-data-background/index.html
http://www.vogella.com/articles/AndroidSQLite/article.html#background_loader
https://github.com/browep/AndroidCursorLoaderTutorial
Edit
private ArrayList<LoginDetails> loginArrayList = new ArrayList<LoginDetails>();;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_listview);
loginList = (ListView)
findViewById(R.id.loginlist);
loginList.setOnItemClickListener(this);
webLogin = (Button)
findViewById(R.id.button3);
webLogin.setOnClickListener(this);
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,loginArrayList );
loginList.setAdapter(loginListAdapter);
populateList();
}
#Override
public void onClick (View v) {
Intent webLoginIntent = new Intent (this, LoginPlusActivity.class);
startActivity(webLoginIntent);
}
public void populateList () {
loginListAdapter.clear();
loginArrayList.clear();
dataStore openHelperClass = new dataStore (this);
SQLiteDatabase sqliteDatabase = openHelperClass.getReadableDatabase();
Cursor cursor = sqliteDatabase.query(dataStore.TABLE_NAME_INFOTABLE, null, null, null, null, null, dataStore.COLUMN_NAME_SITE, null);
startManagingCursor(cursor);
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
loginListAdapter.notifyDatasetChanged();
sqliteDatabase.close();
}
You are losing reference to your listview that why your list isn't updating...
Do this modification in your code.
1. Initialize your ArrayList when it is declared(globally).
ArrayList loginArrayList = new ArrayList<LoginDetails>();
Directly set assign list to Adapter (onCreate)
loginListAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1, loginArrayList);
call populateList() in onCreate().
In your populateList() instead of Adding data to the new list add to existing list associated with your Adapter i.e loginArrayList
if your list is completely new call adapter.clear() and loginArrayList.clear() in the populateList() before adding data to the loginArrayList.
After Adding the data to the loginArrayList call adapter.notifyDataSetChanged()
This should Work...
My recomendation.
Do not do a loop to load your list. If it is a simple list with all
strings. Try to use a SimpleCursorAdapter and will make your app
faster and shorter code.
Once you update the database, then what you do is query the DB to get the Cursor, and to the Adapter use .swapCursor(newCursor). That will update your list while maintaining the scroll position.
If you're manually creating the backing data of the adapter (in this case you're using an ArrayAdapter - which is completely acceptable in a lot of cases) then when the database changes you need to requery the database, recreate your dataset, change the backing dataset of your adapter, and tell the list that the dataset has changed.
A way to accomplish this may be to broadcast an intent that lets your activity know to perform the steps mentioned above (by catching that intent with a BroadcastReceiver).
Here's my sample code for editing the each row as well as the database of the listview I hope it will helps you
First create I create an Adapter name "ListAdapterItem.java"
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class ListAdapterItem extends BaseAdapter {
private ArrayList<HashMap<String, Object>> list;
private Context context;
private RelativeLayout ll;
// used to keep selected position in ListView
private int selectedPos = -1; // init value for not-selected
private TextView label,label_id;
String name,id;
public ListAdapterItem (Context context,ArrayList<HashMap<String, Object>> list) {
this.list = list;
this.context = context;
}
public void setSelectedPosition(int pos) {
selectedPos = pos;
// inform the view of this change
notifyDataSetChanged();
}
public int getSelectedPosition() {
return selectedPos;
}
public View getView(int position, View convertView, ViewGroup parent) {
ll = (RelativeLayout) LayoutInflater.from(this.context).inflate(R.layout.data_list_item, null);
// get text view
label = (TextView) ll.findViewById(R.id.txtview_country_name);
label_id=(TextView) ll.findViewById(R.id.txtview_id);
id=list.get(position).get("Id").toString();
name = list.get(position).get("Name").toString();
label.setText(name);
label_id.setText(id);
return ll;
}
public int getCount() {
return this.list.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
}
And here's my data_list_item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="#+id/txtview_id"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_margin="8dp"
android:layout_marginRight="2dp"
android:textColor="#android:color/black"
android:textSize="22dp"
android:visibility="invisible"/>
<TextView
android:id="#+id/txtview_country_name"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_margin="8dp"
android:layout_marginRight="2dp"
android:textColor="#android:color/black"
android:textSize="22dp" />
</RelativeLayout>
And the main Class "Main.java"
public class Main extends Activity implements OnClickListener {
String name;
SQLiteDatabase db;
Cursor cursor;
private ProgressDialog progressDialog;
public ListAdapterItem list_adapter;
private ArrayList<HashMap<String, Object>> lst_data;
private HashMap<String, Object> hm;
private ListView listview;
private String list_id;
private int counter_id,selectedPosition;
private View selectedView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
lst_data = new ArrayList<HashMap<String, Object>>();
listview = (ListView) findViewById(R.id.list);
new FetchDB().execute();
}
private class FetchDB extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Fetching Data", "Loading,Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... lstStrings)throws IllegalArgumentException {
try {
db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
cursor = db.rawQuery("SELECT * FROM person WHERE Id <> ''",null);
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
hm = new HashMap<String, Object>();
hm.put("Id",cursor.getInt(cursor.getColumnIndex("Id")));
hm.put("Name", cursor.getString(cursor.getColumnIndex("Name")));
lst_data.add(hm);
} while (cursor.moveToNext());
}// end of cursor.moveToFirst()
cursor.close();
}
} catch (Exception e) {
e.getMessage();
}
db.close();// database close
return lst_data;
}// end of doInbackgournd
#Override
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
list_adapter.setSelectedPosition(arg2);
selectedPosition = arg2;
selectedView = arg1;
list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
}
});
}
}// end of FetchDBTask
private class SaveTask extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading,Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... arg0)throws IllegalArgumentException {
counter_id++;
name = editext_name.getText().toString();
hm = new HashMap<String, Object>();
hm.put("Id",counter_id);
hm.put("Name",name);
lst_data.add(hm);
saveDB();
return lst_data;
}// end of doInbackgournd
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
list_adapter.setSelectedPosition(arg2);
selectedPosition = arg2;
selectedView = arg1;
list_id=((TextView) selectedView.findViewById(R.id.txtview_id)).getText().toString();
}
});
}
}// end of saveTask
public void saveDB(){
String sql;
db = openOrCreateDatabase("MyDB", MODE_PRIVATE, null);
// create table if not e exist
db.execSQL("CREATE TABLE IF NOT EXISTS person(Name VARCHAR ,Id INT(3));");
sql = "SELECT * FROM person WHERE Id="+list_id; //selected or click row in list item
Cursor cursor = db.rawQuery(sql, null);
if (cursor.moveToFirst()) {
String sqlUpdate = "UPDATE person SET Name=? WHERE Id="+db_id;
db.execSQL(sqlUpdate, new Object[] {db_name});
cursor.close();
db.close();// database close
} else {// empty insert
String sqlInsert = "INSERT INTO person VALUES (?,"+null+")";
db.execSQL(sqlInsert, new Object[] {db_name,db_address,db_phone,db_email,db_license,db_comments,db_company,db_policy,db_phone_insurance,vehc_year,vehc_make,vehc_model,vehc_license,vehc_vinnum,vehc_color,db_position });
cursor.close();
db.close();// database close
}
}
//Edit by row
private class EditData extends AsyncTask<String, Void,ArrayList<HashMap<String, Object>>> {
protected void onPreExecute() {
progressDialog = ProgressDialog.show(Main.this,"Saving Data", "Loading Please wait...", true);
}
protected ArrayList<HashMap<String, Object>> doInBackground(String... id)throws IllegalArgumentException {
name = editext_name.getText().toString();
hm = new HashMap<String, Object>();
hm.put("Id",counter_id);
hm.put("Name",name);
lst_data.set(selectedPosition, hm); //specific row update
list_id=Integer.parseInt(edit_counter);
saveDB();
return lst_data;
}// end of doInbackgournd
protected void onPostExecute(ArrayList<HashMap<String, Object>> result) {
progressDialog.dismiss();
list_adapter = new ListAdapterItem(Main.this,result);
listview.setAdapter(list_adapter);
}
}
}
And the main_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#android:color/transparent"
android:cacheColorHint="#00000000"
android:dividerHeight="2dp"
android:paddingTop="8dp"
android:transcriptMode="normal" />
</LinearLayout>
Specify your id every listrow in the listview hope that this answer your question
I think that in your populate() method before the while block you should call loginListAdapter.notifyDataSetChanged() and loginListAdapter.clear();
That would clear the adapter and notice to it of the new list of data.
The block will look like this:
loginListAdapter.notifyDataSetChanged();
loginListAdapter.clear();
while (cursor.moveToNext()) {
String sName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_SITE));
String wUrl = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_ADDRESS));
String uName = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_USERNAME));
String pWord = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_PASSWORD));
String lNotes = cursor.getString(cursor.getColumnIndex(dataStore.COLUMN_NAME_NOTES));
LoginDetails lpDetails = new LoginDetails();
lpDetails.setsName(sName);
lpDetails.setwUrl(wUrl);
lpDetails.setuName(uName);
lpDetails.setpWord(pWord);
lpDetails.setlNotes(lNotes);
loginArrayList.add(lpDetails);
webNameList.add(sName);
}
I Just edited because the order you call the notify and clear wasn't correct. The clear must occur after the notify, is just what i got from my experience, unless the adapter wouldn't redraw the list.
Try this code
in public area add variable : List<String> arrayList = new ArrayList<String>();
and in onCreate() add this :
arrayList = populateList();
//then add variable in adapter like this
loginListAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList );
in onResume() this code:
#Override
protected void onResume() {
super.onResume();
loginArrayList.clear();
arrayList.clear();
arrayList = populateList();
loginListAdapter.notifyDataSetChanged()
}
Let us know if you solved it.
I am working with fragments in android,am extending android.app.ListFragment to display listview, but it takes only one item in a list view. I want to display 2 items in a list view ,its possible with extending ListActivity class, but i want to extend both fragment and listactivty.
Refer this image
public class ListFragmentnewforel extends android.app.ListFragment {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ArrayList<HashMap<String, String>> list = buildData();
String[] from = { "purpose" , "name","desc", "num"};
int[] to = { R.id.detailsText1, R.id.detailsText2, R.id.detailsText3, };
SimpleAdapter adapter = new SimpleAdapter(this, list,R.layout.mylistview,from,to);
setListAdapter(adapter);
}
public void onListItemClick(ListView l, View v, int position, long id) {
ArrayList<String>arr=new ArrayList<String>();
String item = (String) getListAdapter().getItem(position);
DetailFragment fragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.detailFragment);
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
fragment.setText(item);
}
else {
Intent intent = new Intent(getActivity().getApplicationContext(),
DetailActivity.class);
Xmlparsingactiforele d=new Xmlparsingactiforele();
arr=d.myelarraylist(item);
// arr.get(0);
intent.putExtra("value1", arr.get(0));
intent.putExtra("value2", arr.get(1));
intent.putExtra("value3", arr.get(2));
intent.putExtra("value4", arr.get(3));
startActivity(intent);
}
}
private ArrayList<HashMap<String, String>> buildData() {
ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
list.add(putData("Android", "Mobile","two", "1"));
list.add(putData("Windows7", "Windows7","one", "2"));
list.add(putData("iPhone", "iPhone","three", "3"));
return list;
}
private HashMap<String, String> putData(String name, String purpose,String a, String n) {
HashMap<String, String> item = new HashMap<String, String>();
item.put("name", name);
item.put("purpose", purpose);
item.put("desc", a);
item.put("num", n);
return item;
}
}
There is nothing stopping you from showing whatever you want in the ListView item. Please read the API documentation of ListFragment.
You can create a ListAdapter that returns the View of the type you want in its getView method. There is hardly any difference between ListActivity and ListFragment in this regard.
Extend both fragment and Activity classes to single Class not possible. So, extends Activity to main class and create inner class and extends Fragment class to in it.
I am using a custom list view through the following code
public class details extends ListActivity {
/** Called when the activity is first created. */
Bundle extras;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_list_view);
extras=getIntent().getExtras();
SimpleAdapter adapter = new SimpleAdapter(
this,
list,
R.layout.custom_row_view,
new String[] {"name","use"},
new int[] {R.id.text1,R.id.text2}
);
populateList();
setListAdapter(adapter);
}
static final ArrayList<HashMap<String,String>> list =
new ArrayList<HashMap<String,String>>();
private void populateList()
{
HashMap<String,String> temp1 = new HashMap<String,String>();
temp1.put("name","NAME");
temp1.put("use",extras.getString("name"));
list.add(temp1);
HashMap<String,String> temp2 = new HashMap<String,String>();
temp2.put("name","CHANGE IN PRICE");
temp2.put("use",extras.getString("change"));
TextView txt=(TextView)findViewById(R.id.text2);
double k=Double.parseDouble(extras.getString("change"));
if(k<0)
{
txt.setTextColor(Color.RED);
}
else
{
txt.setTextColor(Color.RED);
}
list.add(temp2);
}
}
I would like to set the color of the textview to green if change in price is grater than 0 else i want it to be red in color .The following code throws a null pointer exception at the setTextColor(). How exactly do i dothis