android passing object member from alertdialog back to listview - android

I have a button in a TabActivitythat when clicked, opens anAlertDialogwith 2EditTextViews` for a name and number.
When I click the Ok Button to close the Dialog, I want to pass the name back into a ListView on the TabActivity. I can get the name to pass back to the EditText box mAlertDialog on the TabActivity. But something other than the name is being displayed in the ListView.
It looks like a reference to the object "widget" (Widget is an object of the class Device, which has getName, setName methods), com.mypackage.Device#419226e0.
I'll try to post the relevant code below (yes, I know I'm not using Fragments. I found it difficult to implement horizontal scrollable tabs with a ListView with Fragments):
#SuppressWarnings("deprecation")
public class MainActivity extends TabActivity implements OnClickListener {
public static ArrayList<Device> deviceList = new ArrayList<Device>();
public static ArrayAdapter<Device> deviceAdapter=null;
private static ListView deviceListView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTabHost= getTabHost();
TabHost.TabSpec spec;
Intent intent;
rButton = (Button)findViewById(R.id.button_register);
mAlertDialog = (EditText)findViewById(R.id.edittextresult_Name);
rButton.setOnClickListener(onRegister);
intent = new Intent (this, devices.class);
spec = mTabHost.newTabSpec("devices")
.setIndicator("Devices")
.setContent(R.id.devices);
mTabHost.addTab(spec);
deviceListView=(ListView)findViewById(R.id.rdevices);
//Attach array adapter to data array "deviceList"
deviceAdapter = new ArrayAdapter<Device>(this,android.R.layout.simple_list_item_1, deviceList);
//connect adapter "deviceAdapter" to listview widget so the activity listview is populated with data from the array
deviceListView.setAdapter(deviceAdapter);
}
private View.OnClickListener onRegister = new View.OnClickListener() {
public void onClick(View v) {
String title = "Register";
String buttonOk = "OK";
String buttonCancel = "Cancel";
String madd = "address";
String name = "widget name";
//get rdevice.xml view
LayoutInflater li = LayoutInflater.from(context);
View rView = li.inflate(R.layout.rdevice, null);
AlertDialog.Builder adRegister = new AlertDialog.Builder(context);
//set rdevice.xml to adRegister builder
adRegister.setView(rView);
//set title
adRegister.setTitle(title);
//Set EditText views to get user input
final EditText mField = (EditText)rView.findViewById(R.id.editText_Address);
final EditText nField = (EditText)rView.findViewById(R.id.editText_WidgetName);
//set dialog message
adRegister.setMessage("Message")
.setCancelable(false)
.setPositiveButton(buttonOk, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int BUTTON_POSITIVE) {
// TODO Auto-generated method stub
Device widget = new Device();
String madd = mField.getText().toString();
String name = nField.getText().toString();
widget.setName(name);
widget.setAddress(madd);
Log.d(TAG, "Address: " + madd);
Log.d(TAG, "Widget name: " + name);
//get user input and set it to result on main activity
mAlertDialog.setText(nField.getText());
deviceAdapter.add(widget);
deviceAdapter.notifyDataSetChanged();
}
})
.setNegativeButton(buttonCancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int BUTTON_NEGATIVE) {
}
});
//Create alert dialog
AlertDialog alertDialog = adRegister.create();
//show it
adRegister.show();
}
};
On debug, there are no errors in logcat.
However, when I watch the expression mAlertDialog it says
Unable to retrieve the correct enclosing instance of this
Even though the correct name is displayed in the app. When I let the program finish after debug, this reference is displayed in the ListView "com.mypackage.Device#419226e0" instead of the name I typed in the AlertDialog box.
Does this have something to do with scope or anonymous inner classes? Please help. I'm not that familiar with Java so I getting lost in the nuts and bolts here.

Ok I got it to work. This was very helpful: http://www.ezzylearning.com/tutorial.aspx?tid=6816874 , specifically this quote
You may be wondering how the ListView will display the Product object and which property of the Product object will be displayed. The answer is very simple, by default Android ListView control renders a simple TextView inside every ListView item and TextView control can only display simple text. Notice how the toString() function is overridden in the Product class we defined above. Whatever String you will return from the object toString() function will be displayed in the TextView rendered in the ListView items.
Basically, in my Device.java class, I had to override the toString method to specify which object member to pass, so I included this code
#Override
public String toString(){
return this.name;
}

Related

New arraylist item overwrites previous listview item

Currently I'm trying to send intent data from user input to display onto my custom adapter. The intent data from user input from the detailspage.java class will be sent to the listview page with custom Arrayadapter. However each time i add a new item it overwrites my previous entries. Hope some kind souls can help someone new to android.
Below are snippets of my code.
// Set a click listener on that button
btnAddData.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
saveExercise(exerciseName);
}
});
}
private void saveExercise(String name) {
// Read from input fields
// Use trim to eliminate leading or trailing white space
String setString = mSetEditText.getText().toString().trim();
String repString = mRepEditText.getText().toString().trim();
String nameString = name;
Intent intent = new Intent(ExerciseDetailActivity.this, WorkoutSetActivity.class);
intent.putExtra("name", nameString);
intent.putExtra("set", setString);
intent.putExtra("rep", repString);
startActivity(intent);
}
The intent data will be sent to the activity page to initiate the custom ArrayAdapter.
public class WorkoutSetActivity extends AppCompatActivity {
ArrayList<WorkoutSet> workout = new ArrayList<WorkoutSet>();
/** Adapter for the ListView */
WorkoutSetAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.exercise_list);
adapter = new WorkoutSetAdapter(this, workout);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
Intent intent = this.getIntent();
String name = intent.getExtras().getString("name");
String set = intent.getExtras().getString("set");
String rep = intent.getExtras().getString("rep");
adapter.add(new WorkoutSet(name,set,rep));
Toast.makeText(WorkoutSetActivity.this, "Workout added.", Toast.LENGTH_SHORT).show();
adapter.notifyDataSetChanged();
}
}
Lastly the custom ArrayAdapter code. This is where I set the custom listview.
public class WorkoutSetAdapter extends ArrayAdapter<WorkoutSet> {
public WorkoutSetAdapter(Activity context, ArrayList<WorkoutSet> workout) {
super(context, 0, workout);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if the existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.activity_workout_set, parent, false);
}
WorkoutSet currentWorkout = getItem(position);
// Find individual views that we want to modify in the list item layout
TextView nameTextView = (TextView) listItemView.findViewById(R.id.workout_name);
TextView setTextView = (TextView) listItemView.findViewById(R.id.workout_set);
TextView repTextView = (TextView) listItemView.findViewById(R.id.workout_rep);
nameTextView.setText(currentWorkout.getName());
setTextView.setText("Sets: "+ currentWorkout.getSet());
repTextView.setText("Reps: "+ currentWorkout.getRep());
return listItemView;
}
}
each time i add a new item it overwrites my previous entries
There are no "previous entries". startActivity loads an empty adapter each time and you only add one element.
What you want is a SQLite database (or any persistent storage layer, but SQLite is provided without more libraries).
On the plus side, your Intent and Adapter code look fine.
Every time,you call startActivity (), you open a new WorkoutSetActivity, it's a new WorkoutSetActivity object instance, so the arrayAdapter is also new one, it will only display the data you send this time.
If you want to display all the data, you must save the previous data to database or file. At WorkoutSetActivity onCreate (), you should get the previous data, put them and current data to the adapter.

Weird Behavior about notifyDatasetChanged refreshment

Background
Hi, I am new to Android and trying to get familiar with ListView. So I decide to write a simple program for user to enter quotes and display them in order. I implement a StringAdapter and call the notifyDataSetChanged every time when the user confirms.
Question
The weird thing is that the ListView would sometimes update the oldest quotes and sometimes the newer one. and I don't know the problem.
Please ignore the view data button. In this state, I have entered four quotes:
Quotes: hi - Signature:William Shakespeare
Quotes: hello - Signature:William Shakespeare
Quotes: Virtue is bold and goodness never fearful. - Signature:William Shakespeare
Quotes: Love all, trust a few, do wrong to none. - Signature:William Shakespeare
(in reverse order, meaning in time sequence, it goes 4,3,2,1)
Code
main activity
public class storage extends AppCompatActivity {
// the adapter
private StringAdapter sa;
// the edit text view
public EditText etString,etSignature;
// the list view
public ListView lv;
// the array list to capture the quotes and signature
private ArrayList<String[]> dataString = new ArrayList<String[]>();
// add the string and notify
public void addString(String[] s){
this.dataString.add(0,s);
((BaseAdapter)this.lv.getAdapter()).notifyDataSetChanged();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage);
// Link the view elements
this.etString = (EditText) findViewById(R.id.etInput);
this.etSignature = (EditText) findViewById(R.id.etSignature);
this.lv = (ListView) findViewById(R.id.stringList);
Button btn_confirm = (Button) findViewById(R.id.btnConfirm),
btn_viewData = (Button) findViewById(R.id.btnViewData);
// load the adapter
this.sa = new StringAdapter(this,this.dataString);
lv.setAdapter(sa);
btn_confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
storage s = (storage) v.getContext();
// get the String
String sString = s.etString.getText().toString(),
sSignature = s.etSignature.getText().toString();
System.out.println("Quotes: " + sString + "\nSignature:" + sSignature);
// verify it is not empty
if (!sString.isEmpty()&&!sSignature.isEmpty()) {
// add new string and notify
s.addString(new String[]{s.etString.getText().toString(),
s.etSignature.getText().toString()});
((StringAdapter) s.lv.getAdapter()).print_stringData();
// prompt the result
Toast.makeText(s.getBaseContext(),
"Enter Quotes from"+etSignature.getText().toString(),Toast.LENGTH_SHORT).show();
} else {
// prompt the result
Toast.makeText(s.getBaseContext(),
"Please Enter Quotes and Signatures!",Toast.LENGTH_SHORT).show();
}
}
});
}
}
StringAdapter
public class StringAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<String[]> dataStrings = new ArrayList<String[]>();
public StringAdapter(Context c,ArrayList<String[]> dataStrings){this.mContext=c;this.dataStrings=dataStrings;}
public int getCount(){return this.dataStrings.size();}
public Object getItem(int position){ return this.dataStrings.get(position);}
public long getItemId(int postion){ return (long) postion;}
public void print_stringData(){
System.out.println("String Adapter Output:");
for(String [] s: this.dataStrings){
System.out.println("Quotes: "+s[0]+"\nSignature:"+s[1]);
}
}
public View getView(int position, View convertView, ViewGroup parent){
LinearLayout ll;
if(convertView == null){
// set the linear layout
ll = new LinearLayout(this.mContext);
ll.setOrientation(LinearLayout.VERTICAL);
ll.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
// get the data and set the text inside
String[] data = this.dataStrings.get(position);
TextView //tvNo = new TextView(this.mContext),
tvString = new TextView(this.mContext),
tvSignature = new TextView(this.mContext);
ll.addView(tvString);
ll.addView(tvSignature);
tvString.setText(data[0]);
tvString.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
tvSignature.setText(data[1]);
tvSignature.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
tvSignature.setGravity(Gravity.RIGHT);
}
else{
ll = (LinearLayout) convertView;
}
return ll;
}
}
Comments
Some might notice that I add the String[] always to the first element. Actually I have tried to add to the last. The weird behavior still exists.
Environment
Android SDK Version: API 23 lollipop
Emulator Version: Nexus S API 23
Yes, of course, you get that error. Why? Because ListView always re-use convertView in your getView function of Adapter.
Look at your if,else:
else{
ll = (LinearLayout) convertView;
}
return ll;
At this block, you tell the adapter reuse the convertView, but you dont re-set the data. As a result, it will show the data of the previous row.
How to resolve it? just set the data in else block as you do in if one.
P/s: you should learn how to use ViewHolder in ListView to avoid laggy in when scrolling.

Trying to launch an intent from a FragmentActivity

I have an android app where a listview displays a few items - 'films', and when you click on an item it gives you the option to delete or update the item. The delete works fine, and when you click update it opens up a new fragment with the details of the film correctly populated in edit text boxes. I'm trying to figure out how to get the update button on this new Fragment to work.
Firstly I have it extending FragmentActivity, so is this an Activity, or a Fragment? Should I be using something else? When I go to add my button on click listener like I did in the previous 'ListFragment' it won't let me call 'getActivity()' or to reference the currently selected item in the list 'getListAdapter()'. What should I be calling here/how do I reference the current Fragment/Activity?
Should I have these outside of the onCreate in a separate method? I know there is a lot of questions here, but I am really trying to understand what exactly is going on. Any help would be really appreciated. Here is what my code looks like for the FragmentActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.film_activity);
//adds listeners to buttons
updateButton = (Button) findViewById(R.id.update_button);
filmTitleView = (EditText) findViewById(R.id.textView_title);
filmDirectorView = (EditText) findViewById(R.id.textView_director);
filmYearView = (EditText) findViewById(R.id.textView_year);
//retrieves object from intent sent through from previous activity
//assigns variables
Intent intObj = getIntent();
filmTitle = (String) intObj
.getSerializableExtra("title");
filmDirector = (String) intObj
.getSerializableExtra("director");
filmYear = (String) intObj
.getSerializableExtra("year");
filmID = (Integer) intObj
.getSerializableExtra("id");
//Greeting message text set
filmTitleView.setText(filmTitle);
filmDirectorView.setText(filmDirector);
filmYearView.setText(filmYear);
System.getProperty("line.separator");
final Film f1 = (Film)(getListAdapter()).getItem(filmID);
updateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getActivity(),MainActivity.class);
Context context = getActivity();
FilmStoreOpenHelper helper = new FilmStoreOpenHelper(context);
SQLiteDatabase db = helper.getWritableDatabase();
FilmDAO dao = SQLiteFilmDAO.getInstance(db);
FilmStore fs1 = FilmStore.getInstance(context);
fs1.addFilm(f1);
boolean updated = dao.update(f1);
if (deleted){
Toast.makeText(getActivity(), ("Film " + f1.getTitle() + " Updated"), Toast.LENGTH_LONG).show();
db.close();
startActivity(i);
}else{
Toast.makeText(getActivity(), "Not Updated, try again", Toast.LENGTH_LONG).show();
}
}
});
}
Replace any calls to getActivity() with this. A FragmentActivity is a special Activity from the support package that is designed to be used with Fragments. If you're developing for higher than API 11, you can use a regular Activity.

android nullpointerexception in function

I'm new to Java/android so a lot of these terms are foreign but am willing to learn. I'm not gonna go into detail on the app as I dont think it's relevant. My issue as it stands, I've used tutorials and pieces of code from a blog and have gotten my code to work. Trying to clean up and organize my code I get a nullpoiner exception when I move one line (creating my autocompletetextview). Below is the code I've used. My 1 line of code that's giving me an issue is
AutoCompleteTextView companyAutoComplete = (AutoCompleteTextView) addAddressDialog.findViewById(R.id.add_record_dialog_autocomplete);
When I move it to right under the start of my function it errors out but when left in place it works like a charm. I'd like to understand why this is.
public void addAddress() {
final Dialog addAddressDialog = new Dialog(this);
final int[] to = new int[] { android.R.id.text1 };
final String[] from = new String[] { "CompanyName" };
// Create a SimpleCursorAdapter for the CompanyName field.
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, android.R.layout. select_dialog_item, null, from, to);
addAddressDialog.setContentView(R.layout.add_record_dialog);
addAddressDialog.setTitle(getString(R.string.add_record_dialog_address_title));
addAddressDialog.setCancelable(true);
final EditText text1 = (EditText) addAddressDialog.findViewById(R.id.add_record_dialog_edittext);
text1.setHint(getString(R.string.add_record_dialog_company_hint));
Button buttonOK1 = (Button) addAddressDialog.findViewById(R.id.add_record_dialog_ok);
buttonOK1.setText(getString(R.string.add_record_dialog_ok_button));
Button buttonCancel1 = (Button) addAddressDialog.findViewById(R.id.add_record_dialog_cancel);
buttonCancel1.setText(getString(R.string.add_record_dialog_cancel_button));
buttonOK1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Bundle addressBundle = new Bundle();
addressBundle.putString("CompanyName", text1.getText().toString());
Intent intent = new Intent(MenuActivity.this, AddAddressActivity.class);
intent.putExtras(addressBundle);
startActivity(intent);
addAddressDialog.dismiss();
}
});
buttonCancel1.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Toast.makeText(getBaseContext(), "Cancel button clicked", Toast.LENGTH_SHORT).show();
addAddressDialog.dismiss();
}
});
AutoCompleteTextView companyAutoComplete = (AutoCompleteTextView) addAddressDialog.findViewById(R.id.add_record_dialog_autocomplete);
companyAutoComplete.setAdapter(adapter);
// Set an OnItemClickListener, to update dependent fields when
// a choice is made in the AutoCompleteTextView.
companyAutoComplete.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> listView, View view,
int position, long id) {
// Get the cursor, positioned to the corresponding row in the
// result set
Cursor cursor = (Cursor) listView.getItemAtPosition(position);
// Get the CompanyID from this row in the database.
String companyID = cursor.getString(cursor.getColumnIndexOrThrow("_id"));
// test to make sure CompanyID returned
Toast.makeText(getBaseContext(), companyID, Toast.LENGTH_SHORT).show();
}
});
// Set the CursorToStringConverter, to provide the labels for the
// choices to be displayed in the AutoCompleteTextView.
adapter.setCursorToStringConverter(new CursorToStringConverter() {
public String convertToString(android.database.Cursor cursor) {
// Get the label for this row out of the "CompanyName" column
final int columnIndex = cursor.getColumnIndexOrThrow("CompanyName");
final String str = cursor.getString(columnIndex);
return str;
}
});
// Set the FilterQueryProvider, to run queries for choices
// that match the specified input.
adapter.setFilterQueryProvider(new FilterQueryProvider() {
public Cursor runQuery(CharSequence constraint) {
Cursor cursorReturn = dbAdapter.getCompanies(constraint != null ? constraint.toString() : null);
startManagingCursor(cursorReturn);
return cursorReturn;
}
});
addAddressDialog.show();
}
This happens because you call setContentView later.
setContentView sets up the layout for the addAddressDialog dialog. If you don't call setContentView, it has no layout items, therefore addAddressDialog.findViewById(...); will be null, and, obviously you cannot cast that to anything, nor can you call setHint on it.
It shouldn't matter where this line of code is in your method, as long as your line with setContentView is called before it.
The only thing that matters is that your findViewById() call is called after the call to setContentView(), i.e. this line:
addAddressDialog.setContentView(R.layout.add_record_dialog);
The XML file add_record_dialog.xml is the View hierarchy that you are traversing to find the view with the ID of add_record_dialog_autocomplete. Until you've given the dialog that view hierarchy, it cannot traverse it, hence you'll be getting a NullPointerException when you try to use your AutoCompleteTextView since it cannot find your view.
EDIT: Also, if you mean you placed it at the VERY start of the method, that will also fail due to the fact that addAddressDialog will be null until your call to
final Dialog addAddressDialog = new Dialog(this);

Acessing data form database on click of listView

I have a ListView in activity1 where I have a few items which are the word from the database . The User Clicks on an item in the Listview and it will navigate to activity2 where it should show the details of the word which are stored in database as column word, definitions . But What appears in Screen2 depends on what item was clicked in Screen 1
For Ex - User Clicks A in Screen 1 - Words starting from A come up in Screen 2. Is there any way to pass the row id so that in next screen the word and definition from the database can be displayed.
Thank you in adv..
code for first activity:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
// TODO Auto-generated method stub
Cursor c = mDictCursor;
c.moveToPosition(position);
Intent i = new Intent(FirstActivity.this, SecondActivity.class);
Bundle bundle=new Bundle();
//intent.putExtra("position",position);
bundle.putLong(DBAdapter.KEY_ROWID, id);
bundle.putString(DBAdapter.KEY_TITLE, c.getString(
c.getColumnIndexOrThrow(DBAdapter.KEY_TITLE)));
bundle.putString(DBAdapter.KEY_DEFINITION, c.getString(
c.getColumnIndexOrThrow(DBAdapter.KEY_DEFINITION)));
i.putExtras(bundle);
startActivity(i);
}
SecondActivity code:
Bundle extras = getIntent().getExtras();
mRowId = extras.getLong(DBAdapter.KEY_ROWID);
String title = extras.getString(DBAdapter.KEY_TITLE);
String body = extras.getString(DBAdapter.KEY_DEFINITION);
TextView word = (TextView) findViewById(R.id.word);
word.setText(title);
TextView definition = (TextView) findViewById(R.id.definition);
definition.setText(body);
}
Whenever I am clicking the listview item it is showing dialog to force close. Please help...
you can use Intent object putExtra(String name, int value) method in Screen1(see1) and pass the intent object to Screen2,in Screen2 use getIntExtra(String name, int defaultValue) method of Intent object(see 2).
1.use startActivity(Intent intent) method in Screen1
2.use getIntent() method in Screen2 to get Intent object which you passed in the Screen1
I guess you are looking something similar like this .
https://market.android.com/developer?pub=acharya
https://market.android.com/details?id=com.acharyaapp.malayalam.aksharam.full
(Those are my apps)
Why dont you try using a Singleton class to store information. One Intent can set it and the other intent can read it. I employed that logic in my apps.
EDIT
public class MySingleton {
private static final MySingleton INSTANCE = new MySingleton();
//TODO ... all your variable as public static variables. eg. KEY_TITLE
private MySingleton() { }
public static MySingleton getInstance()
return INSTANCE;
}
}
Inside activities, use them as normal instances. Just make sure to call the getInstance() instead of constructor to get the shared instance.
hope this helps.

Categories

Resources