Testing a click on an Android ListView with ActivityUnitTestCase - android

I have implemented a ListView that starts a new Activity when a list item is clicked. When I test it manually, it works perfectly. But when I try to do an automated test with ActivityUnitTestCase, I get a NullPointerException as though the ListView was empty.
MainActivity (partial):
public class MainActivity extends ListActivity {
#Override
protected void onResume() {
super.onResume();
String[] items = new String[] {"item 1", "item 2"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
setListAdapter(adapter);
getListView().setOnItemClickListener(new OnItemClickListener () {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
TextView clickedItem = (TextView) view;
CharSequence clickedItemText = clickedItem.getText(); // throws a NullPointerException when running testWithPerformItemClick()!
Intent intent = new Intent(MainActivity.this, ItemDisplayActivity.class);
intent.putExtra("parameter", clickedItemText);
startActivity(intent);
}
});
}
}
The test code that fails:
public class MainActivityTest extends ActivityUnitTestCase<MainActivity> {
ListView listView;
View child0;
public MainActivityTest() {
super(MainActivity.class);
}
private void setUpTest() {
MainActivity activity = startActivity(new Intent(), null, null);
getInstrumentation().callActivityOnStart(activity);
getInstrumentation().callActivityOnResume(activity);
listView = (ListView) activity.findViewById(android.R.id.list);
child0 = listView.getChildAt(0); // returns null!
}
public void testWithPerformClick() {
setUpTest();
child0.performClick(); // throws a NullPointerException!
Intent startedIntent = getStartedActivityIntent();
assertEquals("item 1", startedIntent.getStringExtra("parameter"));
}
public void testWithPerformItemClick() {
setUpTest();
long itemId = listView.getAdapter().getItemId(0);
listView.performItemClick(child0, 0, itemId); // throws a NullPointerException!
Intent startedIntent = getStartedActivityIntent();
assertEquals("item 1", startedIntent.getStringExtra("parameter"));
}
Both test methods fail because listView.getChildAt(0) returns null. Why is the ListView empty? How can I force it to update itself with the right children?

According to the documentation, If you prefer a functional test you should use ActivityInstrumentationTestCase2. To perform a click it works better. The #fewe answer is right, you have to wait the list to be drawn, to wait the fragment to be loaded you can use getInstrumentation().waitForIdleSync();
Try something like this.
public class ActivityTests extends
ActivityInstrumentationTestCase2<Activity>
final ListView list = (ListView) mActivity.findViewById(R.id.listId);
assertNotNull("The list was not loaded", list);
getInstrumentation().runOnMainSync(new Runnable() {
#Override
public void run() {
list.performItemClick(list.getAdapter().getView(position, null, null),
position, list.getAdapter().getItemId(position));
}
});
getInstrumentation().waitForIdleSync();
Then you cant test, for example, if a fragment was loaded.
mFragment frag = mActivity.getFragment();
assertNotNull("Fragment was not loaded", frag);

This is because the listview isn't drawn yet. You should wait for it to be drawn before trying to access its cells

Related

Update Listview in first activity after returning from second activity

I have a List View in one activity with one info icon in custom adapter. When user taps on that info button then the next activity will open and after marking attendance in next activity when user taps the update button then the second activity should finish and first activity listview should be updated.
What i successfully did:
I have successfully mark the attendance and change the color of listview but i did that after closing the second activity and restarting the first activity. In this way the listview gets updated because of starting activity again.
What I am unable to do:
I want that when user taps on update button then only finish() will call and user returns to previous first activity with listview updated. But when i do so then the listview not get updated. I have to go back and open the activity again then the listview gets updated otherwise not. I do not want that. I also tried to notify adapter in the onResume method of first activity so that when user returns from second activity then the first activity listview adapter will be updated because of onResume method but it isn't work. Please Help
My Listview Activity Code:
public class TeacherWebserviceMainList extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist );
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
//cusadapter.
CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
listcontent.setAdapter(adapter);
}
}
}
}
private void Rsults() {
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
}
My List Adapter Code
public class CustomAdapterTeacherWebservice extends BaseAdapter {
private static ArrayList<DetailsTeacherwebservice> searchArrayList;
DatabaseHandler databaseHandler;
private Context context;
private LayoutInflater mInflater;
public CustomAdapterTeacherWebservice(Context context, ArrayList<DetailsTeacherwebservice> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
databaseHandler = new DatabaseHandler(context);
}
#Override
public int getCount() {
return searchArrayList.size();
}
#Override
public Object getItem(int p) {
return searchArrayList.get(p);
}
#Override
public long getItemId(int p) {
return p;
}
public int getViewTypeCount() {
return 500;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public View getView(final int p, View v, ViewGroup parent) {
ViewHolder holder;
context = parent.getContext();
if (v == null) {
v = mInflater
.inflate(R.layout.teacherwebserviceadapter, null);
holder = new ViewHolder();
holder.name = (TextView) v.findViewById(R.id.teacher_name);
holder.cnic = (TextView) v.findViewById(R.id.teacher_cnic);
holder.no = (TextView) v.findViewById(R.id.teacher_phone);
holder.gender = (TextView) v.findViewById(R.id.gender);
holder.status = (TextView) v.findViewById(R.id.status);
holder.info = (ImageView) v.findViewById(R.id.edit);
holder.l1 = (LinearLayout) v.findViewById(R.id.main);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.name.setText(searchArrayList.get(p).getTeachername());
holder.cnic.setText(searchArrayList.get(p).getTeachercnic());
holder.no.setText(searchArrayList.get(p).getTeacherno());
holder.gender.setText(searchArrayList.get(p).getTeachergender());
holder.status.setText(searchArrayList.get(p).getAttendance());
if (searchArrayList.get(p).getAttendance().equals("Absent"))
{
holder.l1.setBackgroundColor(Color.parseColor("#DB674D"));
}
if (searchArrayList.get(p).getAttendance().equals("Present"))
{
holder.l1.setBackgroundColor(Color.parseColor("#7EB674"));
}
if (searchArrayList.get(p).getAttendance().equals("Transfer Out"))
{
holder.l1.setBackgroundColor(Color.parseColor("#FBE87C"));
}
if (searchArrayList.get(p).getAttendance().equals("Resigned"))
{
holder.l1.setBackgroundColor(Color.parseColor("#4FC3F7"));
}
holder.info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent view_order_intent = new Intent(context, Teacherwebservicemainlistupdate.class);
view_order_intent.putExtra("ID", searchArrayList.get(p).getId());
view_order_intent.putExtra("tname", searchArrayList.get(p).getTeachername());
view_order_intent.putExtra("tgender", searchArrayList.get(p).getTeachergender());
view_order_intent.putExtra("tcnic", searchArrayList.get(p).getTeachercnic());
view_order_intent.putExtra("tno", searchArrayList.get(p).getTeacherno());
view_order_intent.putExtra("tatt", searchArrayList.get(p).getAttendance());
view_order_intent.putExtra("tattdetails", searchArrayList.get(p).getTeacherattendancedetails());
view_order_intent.putExtra("tattdatesince", searchArrayList.get(p).getAttendancedatesince());
view_order_intent.putExtra("tatttrasnferout", searchArrayList.get(p).getAttendancetrasnferschool());
//context.startActivity(view_order_intent);
((Activity)context).startActivityForResult(view_order_intent, 1);
}
});
return v;
}
static class ViewHolder {
TextView name, cnic, no, gender,status;
ImageView info;
LinearLayout l1;
}
here in adapter code when INFO button is clicked then another activity starts in which user can update the attendance.
This is Update activity code when button clicked:
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DetailsTeacherwebservice schoolinfo = new DetailsTeacherwebservice();
schoolinfo.setTeachername(teachername.getText().toString());
schoolinfo.setTeacherno(teacherno.getText().toString());
schoolinfo.setTeachercnic(teachercnic.getText().toString());
schoolinfo.setTeachergender(teachergender.getText().toString());
schoolinfo.setAttendance(teachergroupstr);
schoolinfo.setTeacherattendancedetails(absentgrpstr);
schoolinfo.setAttendancedatesince(txtDate.getText().toString());
schoolinfo.setAttendancetrasnferschool(transferOutSchool.getText().toString());
databasehandler.updateteacherwebservice(schoolinfo, emis, identity);
Toast.makeText(Teacherwebservicemainlistupdate.this, "Updated Successfully", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.putExtra("update", "1");
setResult(RESULT_OK, intent);
finish();
}
}
});
I can start the listview activity again when update button is clicked but that changes the index of the list item clicked i.e. because activity starts again. How ever what i want is that if i clicked on 10th item then when next activity opens and user updates attendance then it returns back to previous activity on same index position so that the user do not have to scroll again to go back on 10th item
Add this code for list item click:
Intent i = new Intent(context, YourAcitivityName.class);
i.putExtra("position",p);
startActivityForResult(i, 1);
Add this code in update button:
Intent intent = new Intent();
intent.putExtra("update", "1");
intent.putExtra("position",getIntent().getIntExtra("position",0));
setResult(RESULT_OK, intent);
finish();
When you get back from activity to the activity where list view is implemented this method called:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
// add your code to update list view
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
YourAdapterClassName adapter = new YourAdapterClassName(this, arrList);
listView.setAdapter(adapter);
listView.smoothScrollToPosition(getIntent().getIntExtra("position",0));
}
}
}
}
The following are two examples, the first is an example where the source for the ListView is a List (and in this case using a Custom Adapter), the second is where the source is a Cursor (using SimpleCursorAdapter)
The trap many fall into is just updating the List using something like :-
myList = method();
myAdapter.notifyDataSetChanged();
At a guess, that's the trap you've fallen into.
When what should be done is to use the List's methods to alter it (e.g. clear, add, addAll, remove).
I believe this explains the reasoning - Is Java “pass-by-reference” or “pass-by-value”?
Example 1 - List as the source :-
/**
* Build or rebuild the List of TaskData's, instantiate the
* Custom Array Adapter if needed and also notify the adapter
* if the List may have been changed.
*/
private void prepTasksCustomArrayList() {
// Determine if the adpater needs to be notified of changes
boolean notify_dataset_changed = (mCsr != null && mCustomArrayAdapter != null);
// If the List is not null then assume that it has changed
// otherwise just get the List
if (mTasks != null) {
mTasks.clear();
mTasks.addAll(dbhlpr.getAllTasks());
} else {
mTasks = dbhlpr.getAllTasks();
}
// If the adapter is null then instantiate it
if (mCustomArrayAdapter == null) {
mCustomArrayAdapter = new CustomArrayAdapter(
this,
R.layout.taskdata_item,
mTasks);
}
// Notify the adapter that the List has changed
if (notify_dataset_changed) {
mCustomArrayAdapter.notifyDataSetChanged();
}
}
Notes
This is used to both setup and alter/update the ListView that the adpater is attached to.
All that is needed is to call the method at the appropriate place/s in the code e.g. in the Activities onCreate, onResume, after onItemClick/LongClick.
e.g in onCreate :-
mTaskList = this.findViewById(R.id.tasklist); // The ListView
prepTasksCustomArrayList()
mTaskList.setAdapter(mCustomArrayAdapter)
and in onresume just (in conjunction with the 3 lines in onCreate)
prepTasksCustomArrayList()
I don't believe that this way is very common, normally you see the adapter being setup in onCreate.
mTasks.addAll(dbhlpr.getAllTasks()); is what gets the source data.
Example 2 - Cursor as the Source
/**
* Build or rebuild the List via Cursor using the bespoke layout
*/
private void prepCursorListBespoke() {
boolean swapcursor = (mCsr != null && mCursorAdapter2 != null);
if (mCursorAdapter2 == null) {
mCursorAdapter2 = new SimpleCursorAdapter(this,R.layout.taskdata_item,mCsr,
new String[]{ Datasource.TASKS_ID_COL,
Datasource.TASKS_TYPE_COL,
Datasource.TASKS_NAME_COL,
Datasource.TASKS_OWNER_COL,
Datasource.TASKS_EXPIRATION_COL},
new int[]{R.id.task_id,
R.id.task_type,
R.id.task_name,
R.id.task_owner,
R.id.task_expiration},
0);
}
if (swapcursor) {
mCursorAdapter2.swapCursor(mCsr);
}
}
Notes
The prepCursorListBespoke method is used in the same way as for example 1.
notifyDataSetChanged could be used instead of swapCursor
I use swapCursor because it's more descriptive).
However, you can only use swapCursor for Cursors.
Added
The following changes may work, roughly speaking I've applied the List example above.
i.e. Rsults is called by onResume(added) which will notify the adapter that the data has been changed.
The code hasn't been tested as there was insufficient code. (a no code for DatabaseHandler class, and b) no code for DetailsTeacherwebservice class). As such there may be errors.
Look for //++++++++++++++... comments should follow to say what has been done/changed.
public class MainActivity extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist);
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//MOVED On ItemClickListener block FROM Rsults to here.
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
// Probably don't even need onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if (update.equals("1")) {
//cusadapter.
//CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
//+++++++++++++++++++++++++++++++++++
// Commented out
//listcontent.setAdapter(adapter);
}
}
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Added onResume to call Rsults
#Override
public void onResume() {
super.onResume();
Rsults();
}
private void Rsults() {
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ADDED 4 lines to see if the notifyDataSetChanged is required
boolean notifydschg_needed = false;
if (cusadapter != null) {
notifydschg_needed = true;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// YOU NEED TO GET THE TEACHER LIST AGAIN AS THE DB HAS CHANGED
teacherList = databasehandler.teacherwebserviceList(emis);
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Just create the adapter and attach it to the listview once
if (cusadapter == null) {
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Notify the adapter that the data has been changed
if(notifydschg_needed) {
cusadapter.notifyDataSetChanged();
}
}
}
// you have to set data in adapter in onResume method
#Override
protected void onResume() {
super.onResume();
}
You can use eventbus for this case:
This is an example:
In your build.gradle file
compile 'org.greenrobot:eventbus:3.0.0'
In Activity has listview:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this); // register event
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this); // unregister event
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EventBusInfo eventBusInfo) {
if (eventBusInfo.getProcessId() == 99) {
// eventBusInfo.getData();
notifyDataSetChanged();
}
}
In Update Activity
yourButtonFinish.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
EventBusInfo event = new EventBusInfo();
event.setProcessId(99);
//event.setData(object) //if you want get data back
EventBus.getDefault().post(event);
}
});
Class EventBusInfo
public class EventBusInfo {
private int processId;
private Object data;
public EventBusInfo(int processId, Object data) {
this.processId = processId;
this.data = data;
}
public EventBusInfo() {
}
public EventBusInfo(int processId) {
this.processId = processId;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getProcessId() {
return processId;
}
public void setProcessId(int processId) {
this.processId = processId;
}
}
save the list items in every change then restart the Activity of adapter with intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) to close the old ListView.
Is what I do and it works fine.
if the list it is not empty, I restart the activity with the adapter and I have a new ListView closing the previous one. Or if it is empty, I start a different activity (to not have an empty ListView)
Saving and loading the list items every time to SharedPreferences with Gson
For a reason notifyDataSetChanged() does not work good in my case so I prefer this solution.

How to get item details from Listview on another activity

I have tried many methods but still not working.
almost used all methods from stackoverflow's answers. but not working.
MainActivity.java
mProductList = new ArrayList<>();
//add sample data to list
mProductList.add(new Product(1, "iPhone4", 200, "Apple1"));
mProductList.add(new Product(2, "iPhone5", 2100, "Apple2"));
mProductList.add(new Product(3, "iPhone6", 2020, "Apple3"));
mProductList.add(new Product(4, "iPhone7", 2400, "Apple4"));
mProductList.add(new Product(5, "iPhone8", 2050, "Apple5"));
mProductList.add(new Product(6, "iPhone9", 7200, "Apple6"));
//init adapter
adapter = new ProductListAdapter(getApplicationContext(), mProductList);
lvProduct.setAdapter(adapter);
lvProduct.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), "Clicked product id =" + view.getTag(), Toast.LENGTH_SHORT).show();
Product item = (Product)lvProduct.getAdapter().getItem(position);
Log.d("abc",item.getName());
Intent launchActivity1= new Intent(MainActivity.this,Show.class);
launchActivity1.putExtra("item", item.getName());
startActivity(launchActivity1);
}
});
and Show.java
public class Show extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
}
Intent launchActivity1 = getIntent();
String item = launchActivity1.getStringExtra("item"); // this is line 17
}
when i click on one item it shows item name in Log with "getName()" function.
but at the same time app crashes and show error in Show.java on line 17
please help me to solve this code.
this error is showing in Log
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.Serializable android.content.Intent.getSerializableExtra(java.lang.String)' on a null object reference
at com.example.sohaib.mydesign.Show.<init>(Show.java:17)
Your code is outside onCreate method!
Intent launchActivity1 = getIntent();
String item = launchActivity1.getStringExtra("item");
Put this inside onCreate. Also onCreate doesn't have override annotation.
Copy paste this instead in your Show.java
public class Show extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
Intent launchActivity1 = getIntent();
String item = launchActivity1.getStringExtra("item"); // this is line 17
}
}
add it in oncreate block...
public class Show extends Activity {
protected void onCreate(Bundle savedInstanceState) {
................
................
Intent launchActivity1 = getIntent();
String item = launchActivity1.getStringExtra("item"); // this is line 17
}
}
Or it happens when you pass object instead of string. So use
launchActivity1.putExtra("item", ""+item.getName());
thanks..
and in onclick should be..
Product item = (Product)parent.getAdapter().getItem(position);
I have Solved the issue on my own. thank you all of you for your quick response... solution is...
MainActivity.java
lvProduct.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(), "Clicked product id =" + view.getTag(), Toast.LENGTH_SHORT).show();
Product item = (Product)lvProduct.getAdapter().getItem(position);
Intent launchActivity1= new Intent(MainActivity.this,Show.class);
launchActivity1.putExtra("item", item.getName());
startActivity(launchActivity1);
}
});
Show.java
public class Show extends Activity {
String passedVar = null;
private TextView passedView= null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show);
passedVar = getIntent().getStringExtra("item");
passedView = (TextView) findViewById(R.id.pass);
passedView.setText("You= " + passedVar);
}
}

Setting On Click Listener For A Dynamic ListView

thanks for always being available...
I have been able to populate my ListView with information i have in the database.
Now, I want setOnClickListener for the items to go to different pages. Currently, I am using a "switch(position)" construct, but it doesn't function appropriately since I can't hard code how many items would be on the ListView.
Please, kindly help me out on this one.
public class SurveyActivity extends AppCompatActivity {
ArrayList<String> list = new ArrayList<String>();
SQLiteDatabase db;
DatabaseHelper helper = new DatabaseHelper(this);
String listItem = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_survey);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Add new survey", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
PopupMenu pop = new PopupMenu(SurveyActivity.this, fab);
pop.getMenuInflater().inflate(R.menu.addsurvey_menu, pop.getMenu());
pop.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(getApplicationContext(), "Your choice is to " + item.getTitle().toString().toUpperCase() + " a survey form", Toast.LENGTH_LONG).show();
switch (item.getItemId()) {
case R.id.c:
//Takes admin to page where survey is created
Intent i = new Intent(getApplicationContext(), CreateSurvey.class);
startActivity(i);
case R.id.d:
//gets ready created XML forms from server
case R.id.r:
//refreshes and updates survey list from db
}
return true;
}
});
pop.show();
}
});
db = helper.getReadableDatabase();
//Cursor crs = db.rawQuery("SELECT * FROM tbNames", null);
Cursor crs=db.query("tbNames",new String[]{ "names"},null,null,null,null,null);
if(crs.moveToFirst()){
do {
listItem =crs.getString(0);
list.add(listItem);
}while(crs.moveToNext());
}
ListView surveyList = (ListView) findViewById(R.id.surveylist);
ArrayAdapter<String> aAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
surveyList.setAdapter(aAdapter);
registerForContextMenu(surveyList);
surveyList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (position) {
case 0:
Intent i = new Intent(getApplicationContext(), hivActivity.class);
startActivity(i);
break;
case 1:
Intent intent = new Intent(SurveyActivity.this, CreatedSurveyActivity.class);
startActivity(intent);
}
}
});
}
}
My app would allow users create multiple surveys which would show up in the LIstView.
The problem is how to set Listeners for the items dynamically too.
You can try this code
surveyList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (position == 0) {
Intent i = new Intent(getApplicationContext(), hivActivity.class);
startActivity(i);
} else {
Intent intent = new Intent(SurveyActivity.this, CreatedSurveyActivity.class);
startActivity(intent);
}
}
});
First item will call hivActivity and all other items will call CreatedSurveyActivity. If you need to pass something to the CreatedSurveyActivity put it into the intent, like this intent.putExtra("position" position);
Maybe use setOnItemClickListener()
Posting your code would be helpful, however an approach that can often help in similar situations is:
Set a tag on each view, as you generate it. For example, the item ID, or just an incrementer.
The onClickListener will receive the view as a parameter. The tag can then be retrieved from it.
This tag can then be matched to page names, page URLs, or any other information you're trying to load.

Passing values to Activities with putExtra()

I am trying to pass a value on my ListView to my second activity using Intents. I am not sure how to pass the text value to the second activity my Intent leads to. Right now my Intent is able to connect to the second activity on tap but it doesn't pass the string of the tapped value.
I feel that I need to pass something into my launchEditItem() but I am not sure what. These are the two functions I am dealing with right now.
private void launchEditItem() {
Intent i = new Intent(this, EditItemActivity.class);
i.putExtra("itemOnList", ); // list item into edit text
startActivity(i);
}
private void setupEditItemListener() { // on click, run this function to display edit page
lvItems.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View item, int pos, long id) {
launchEditItem();
}
});
}
I'm not sure what value to place into the i.putExtra(), but I think I need to pass an argument into the launchEditItem().
This is what is currently in my second Activity:
public class EditItemActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_item);
Intent i = getIntent();
String ItemToEdit = i.getStringExtra("itemOnList");
// place into EditText using ItemToEdit
}
I'm also not sure how to place this String value (ItemToEdit) into an EditText box. I'm new to android dev so I'm learning as much as I can thank you!
* EDIT *
I guess I'm a bit too vague in my question. Here is the entire code of the small app I am working on
public class ToDoActivity extends Activity {
private ArrayList<String> todoItems;
private ArrayAdapter<String> todoAdapter; // declare array adapter which will translate the piece of data to teh view
private ListView lvItems; // attach to list view
private EditText etNewItem;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do);
etNewItem = (EditText) findViewById(R.id.etNewItem);
lvItems = (ListView) findViewById(R.id.lvItems); // now we have access to ListView
//populateArrayItems(); // call function
readItems(); // read items from file
todoAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, todoItems); //create adapter
lvItems.setAdapter(todoAdapter); // populate listview using the adapter
//todoAdapter.add("item 4");
setupListViewListener();
setupEditItemListener();
}
private void launchEditItem() {
Intent i = new Intent(this, EditItemActivity.class);
i.putExtra("itemOnList", ); // list item into edit text
startActivity(i);
}
private void setupEditItemListener() { // on click, run this function to display edit page
lvItems.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View item, int pos, long id) {
launchEditItem();
}
});
}
private void setupListViewListener() {
lvItems.setOnItemLongClickListener(new OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapter, View item, int pos, long id) {
todoItems.remove(pos);
todoAdapter.notifyDataSetChanged(); // has adapter look back at the array list and refresh it's data and repopulate the view
writeItems();
return true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.to_do, menu);
return true;
}
public void onAddedItem(View v) {
String itemText = etNewItem.getText().toString();
todoAdapter.add(itemText); // add to adapter
etNewItem.setText(""); //clear edit text
writeItems(); //each time to add item, you want to write to file to memorize
}
private void readItems() {
File filesDir = getFilesDir(); //return path where files can be created for android
File todoFile = new File(filesDir, "todo.txt");
try {
todoItems = new ArrayList<String>(FileUtils.readLines(todoFile)); //populate with read
}catch (IOException e) { // if files doesn't exist
todoItems = new ArrayList<String>();
}
}
private void writeItems() {
File filesDir = getFilesDir(); //return path where files can be created for android
File todoFile = new File(filesDir, "todo.txt");
try {
FileUtils.writeLines(todoFile, todoItems); // pass todoItems to todoFile
} catch (IOException e) {
e.printStackTrace();
}
}
}
String[] link_list;
int currenttrack=0;
link_list=new String[]{
"W-TE_Ys4iwM",//1
"oozgmH3ZP14",//2
"o_v9MY_FMcw",//3
"36mCEZzzQ3o",//4
}
First activity
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
currenttrack=arg2;
Intent videoIntent=new Intent(MainActivity.this,VideoView.class);
videoIntent.putExtra("filename", link_list[currenttrack]);
startActivity(videoIntent);
}
});
In your Second Activity
// getting intent data
// get intent data
Intent i = getIntent();
Bundle extras = i.getExtras();
filename = extras.getString("filename");
Log.e("File Name", filename);
and your done :)
In your current Activity, create a new Intent:
Intent i = new Intent(getApplicationContext(), NewActivity.class);
i.putExtra("new_variable_name","value");
startActivity(i);
Then in the new Activity, retrieve those values:
Bundle extras = getIntent().getExtras();
if (extras != null) {
String value = extras.getString("new_variable_name");
}
I am not sure if i understood where is the value. Well if the value is in EditText do something like:
private void launchEditItem(String text) {
Intent i = new Intent(this, EditItemActivity.class);
i.putExtra("itemOnList", text); // list item into edit text
startActivity(i);
}
private void setupEditItemListener() { // on click, run this function to display edit page
lvItems.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adapter, View item, int pos, long id) {
EditText editView = (EditText) item.findById(R.id.ItemToEdit);
String text = editView != null ? editView.getText().toString() : "";
launchEditItem(text);
}
});
}
1 - I have some doubt with:
i.putExtra("itemOnList", );
You'd better pass a value:
i.putExtra("itemOnList", "something");
2 - To valorize a control, you must obtain a reference to it first. Something like:
EditText edt =
(EditText) findViewById(R.id.activity_edit_item_my_EditText); // or whatever id you assigned to it (it MUST HAVE AN ID)
Do it AFTER setContentView().
Then you can set it's text like:
edt.setText(ItemToEdit); // Now it should contain "something"
Just as simple as that
[EDIT]
If you aren't sure what to pass so is to pass in the "tapped" value in the ListView into the putExtra, modify your listview click handler code:
list.setOnItemClickListener
(
new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
// TODO Auto-generated method stub
Intent videoIntent = new Intent(MainActivity.this, VideoView.class);
videoIntent.putExtra("filename", (((TextView) v).getText().toString());
startActivity(videoIntent);
}
}
);
It should work immediately.
01: Current Activity
String pass_value ="value";
Intent intent = new Intent(getApplicationContext(),NewActivity.class);
intent.putExtra("var_name",pass_value);
startActivity(intent);
02: New Activity
String value = getIntent().getExtras().getString("var_name");

Activity missing data on return

So I have my main activity which holds a list view and has a map which holds all my data for the list. Upon clicking on an item you are taken to a details display. When I press the back button to get back to the main activity from the detail activity, if I set a break point, my map keys are still intact, but all the strings in the objects are "" and the ints are -1. Here is what my main activity looks like:
public class MainActivity extends Activity {
private Map<String, Stunt> stunts = new LinkedHashMap<String, Stunt>();
private StuntsDao stuntsDao;
private ListAdapter listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stuntsDao = new StuntsDao(getApplicationContext());
stunts = stuntsDao.getAllStunts();
listAdapter = new ListAdapter(this, R.layout.list_layout, new ArrayList<Stunt>(stunts.values()));
ListView listView = (ListView)findViewById(R.id.listView);
listView.setAdapter(listAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String stuntName = (String)((ViewHolder)view.getTag()).stuntName.getText();
Intent myIntent = new Intent(getApplicationContext(), StuntDetails.class);
getStuntDetailsIfNeeded(stuntName);
Stunt stunt = stunts.get(stuntName);
myIntent.putExtra("STUNT", stunt);
startActivity(myIntent);
}
});
}
...
}
Why would the objects in my map be basically empty?
onCreate() doesn't get called when you click back. You need to init your data again in onStart or onResume. See: http://developer.android.com/training/basics/activity-lifecycle/starting.html

Categories

Resources