Android notifyDataSetChanged behave differently - android

I have two different applications, that update a list in both cases.
App1
addButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dataList.add("NEW CITY");
cityAdapter.notifyDataSetChanged();
}
});
Here, my floating action button, update the list with const string (as test input). If I don't use notifyDataSetChanged the list will not show the 'NEW CITY' text.
App2
This one is a bit more complex than the App1, because now use a fragment to add/edit city.
The two listeners looks like this.
addCityButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
new AddCityFragment().show(getSupportFragmentManager(),"ADD_CITY");
}
});
cityList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
City clickedCity = cityAdapter.getItem(i);
AddCityFragment.newInstance(clickedCity, i).show(getSupportFragmentManager(),
"EDIT_CITY");
return false;
}
});
I have two methods that implement the logic which are invoked when the fragment is loaded.
#Override
public void onOkPressListener(City newCity) {
dataList.add(newCity);
}
#Override
public void onEditPressListener(City editCity, int index) {
City currentCity = dataList.get(index);
currentCity.setCity(editCity.getCity());
currentCity.setProvince(editCity.getProvince());
}
For some reason, the list updates (add/edit) even though I didn't call notifyDataSetChanged in each method. Is the list refreshed somehow when the fragment is closed? I feel like I ignore some sort of a Android activity lifecycle method here.

Related

Android: Custom dialog view, change button color before showing for first time

I'm making something like a social app.
I would like that if someone has already viewed something before, that the button in the view will change colors.
I have a method to check if someone has viewed this list before. It works in the clickListener, and will say "Already pressed."
I'm having a hard time figuring out how to change the color of the button, maybe on the onCreate method. I've tried passing it as an argument, but the color will change on the second time the list is pulled up...
This is how I call up my dialog and pass it the list ID.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View r = inflater.inflate(R.layout.list_view_dialog_layout, container, false);
checklistView = (UserlistView) r.findViewById(R.id.user_list);
checklistview.getList(getArguments().getString("list_id")); // Can be modified
return r;
}
in that function getList, I make my call to my database to get the info of the list.
public void getList(final String listID) {
// TODO fetch list information from params and fill fields
Event.requestEvent(listID, "AuthToken", new List.ListReceivedListener() {
#Override
public void onListReceived(lissts... lissteses) {
List lst = lissteses[0];
setInfo(lst);
LISTID = listID;
}
});
}
public void setInfo(List lst){
listTitleView.setText(lst.listName);
viewsCount.setText(Integer.toString(lst.views));
}
I have a checker function to see if the user has already clicked the "have viewed"
public static boolean viewed(String id, final String user){
DatabaseReference rootref = FirebaseDatabase.getInstance().getReference("views").child(id);
rootref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(user)){
result = true;
}
else{
result = false;
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return result;
}
then, I wanted to call it in the getList() as such
if(viewed(lstID, curuser){
viewButton.setColorFilter(R.color.blue);
}
this doesn't work for the first time the view is created, and so, if the user has already clicked view, logs out and logs back in, and click view again, messing up the view count.
int flag=0;
button.setOnClickLitener(new OnClickListener()){
#Override
public void onClick(View arg0) {
flag++;
}
});
if(flag>0){
button.setBackgroundColor(getResources().getColor(R.color.yourColor));
}
Another solution is this.
button.setBackgroundColor(getResources().getColor(R.color.youCustomColor));

RecyclerView onItemClick() imitation, is it good practice?

I saw some different ways of implementing onItemClickListener for RecyclerView. My favourite is to use interface callback:
Interface:
public interface OnClickListener {
void onCardClick(View v);
void onFavouriteButtonClick(View v);
void onRemoveClick(View v);
//Other clickable areas
}
In adapter:
currentView.favouriteButton.setTag(currentItem.getId());
currentView.favouriteButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (OnClickListener != null){
OnClickListener.onFavouriteButtonClick(v);
}
}
});
In main activity/fragment
adapter = new CardAdapter( .... new OnClickListener() {
#Override
public void onFavouriteButtonClick(View v) {
int id = Integer.parse(v.getTag().toString());
//Do your stuff
}
....
});
So, I have some questions:
is it good way of handling things?
will performance be slow if number of items will grow?
any reasons why I shouldn't use this approach?
I think you could improve upon this by not passing the view outside of the adapter.
// Create an object that encapulates the information for each card
public class CardInfo {
// Whatever you want to show in your card
}
// Create a listener for items instead of views
public interface OnCardAction {
void onCardSelected(CardInfo cardInfo);
void onFavoriteSelected(CardInfo cardInfo);
void onCardRemoved(CardInfo cardInfo);
}
// In your adapter
favoriteButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// You many need to check if onCardActionLisetner is null
CardInfo cardInfo = getItemAt(viewHolder.getAdapterPosition());
onCardActionListener.onFavoriteSelected(cardInfo);
}
});
NOTE: If you are passing the listener in the constructor can either make it required (throw error if it is null) or not even create View.OnClickListner to reduce the number of null checks.

Mortar: How-to use Presenter for List Item/Adapter

I using a List with Custom Adapter with ViewHolder and Item Views with Buttons.
I want to handle some stuff by clicking the Buttons in a Presenter.
How can i connect a Presenter with these Item Views?
You can use rx-android to observe AdapterView's click events the following way. It combines fine with MVP pattern used in Mortar.
At first dependencies:
compile 'io.reactivex:rxjava:1.0.4'
compile 'io.reactivex:rxandroid:0.24.0'
Then create observeClicks method in your view class.
public Observable<OnItemClickEvent> observeClicks() {
return WidgetObservable.itemClicks(adapterView);
}
Subscribe to events in your Presenter's onLoad:
private Subscription clicks;
#Override
protected void onLoad() {
super.onLoad();
clicks = getView().observeClicks().subscribe(
new Action1<OnItemClickEvent>() {
#Override
public void call(OnItemClickEvent event) {
// handle click events
}
}
);
}
protected void onDestroy() {
// unsubscribe from events
clicks.unsubscribe();
}
Also you can do mapping OnItemClickEvent to your data inside view already and observe it instead of raw events.
public Observable<YourDataClass> observeClicks() {
return WidgetObservable.itemClicks(adapterView).
map(new Func1<OnItemClickEvent, YourDataClass>() {
#Override
public YourDataClass call(OnItemClickEvent onItemClickEvent) {
YourDataClass item = adapter.getItem(onItemClickEvent.position());
return item;
}
});
}
Hope this comes in handy. At least I'm doing this that way, but certainly it is not the only solution.
ListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Handle your stuff here.
});
Something like this? Use the position to get the current item out of your List.
Buttons :
// In the adapter
Button butt = (Button) rowView.findViewById(R.id.yourbutton);
butt.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
//Button Action.
}
}

Checkboxes not changing checked status in UI?

I have a ListView that I am trying to use with a checkable item list. I am calling the toggle() method on my list item class in the ArrayAdaptor, but the checkbox is not being ticked in the UI. However, I can confirm that the correct items are being selected in the UI, and that the "isChecked()" status reports back correctly--just the UI doesn't change at all. Are there any special methods I need to call to update the checkbox graphic for the UI?
To put it another way--how do I programmatically tell the UI that a checkbox should show up as "checked"? It seems this should be a very simple process, but I've been having a lot of trouble finding this information.
Code is as follows:
For the item data class in the ArrayAdaptor:
public class SelectedItemData extends CheckedTextView {
public String _item_name;
public String getItemName()
{
return _item_name;
}
public void setItemName(String in_name)
{
_item_name = in_name;
}
// methods
public SelectedItemData(Context context) {
super(context);
init();
}
public void init()
{
this._item_name = "UNSET";
this.setChecked(false);
}
#Override
public String toString()
{
return _item_name;
}
}
In the Activity class (located within the onCreate method):
_selectedItemsListView = (ListView) findViewById(R.id.selected_items_listview);
_selectedItemsListView.setItemsCanFocus(false);
_selectedItemsListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
_selectedItemsListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listview, View view, int position, long id) {
#SuppressWarnings("unchecked")
ArrayAdapter<SelectedItemData> itemsAdapter = (ArrayAdapter<SelectedItemData>)_selectedItemsListView.getAdapter();
SelectedItemData selectedItem = itemsAdapter.getItem(position);
selectedItem.toggle();
Toast.makeText(view.getContext(), "Item " + selectedItem.getItemName() + " Selected!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Is Item Checked? " + selectedItem.isChecked());
_selectedItemsListView.setAdapter(itemsAdapter);
}
});
Any guidance on how to enable the UI to properly display that one of the items have been selected/checked would be great. Thanks!
You have to update your adapter with the new item and set it to the listview. (itemsAdapter.setItem(item,position))

OnclickListener for individual elements in a row from a ListActivity using SimpleCursorAdapter to Bind to DB not working properly

Please help.
As I have stated in the title I am trying to make that individual elements of a row of a List adapter launch different actions depending on what the user click.
It "kind of" works but it takes LONG for it to react to user clicks. What is it that I am doing wrong?
Thanks in advance,
So I tried the following code in
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Get the item that was clicked
Cursor c = (Cursor) this.getListAdapter().getItem(position);
// c.moveToNext();
prescription_id = c.getString(0);
TextView pName = (TextView) v.findViewById(R.id.text2);
TextView paName = (TextView) v.findViewById(R.id.text3);
TextView rDateLabel = (TextView) v.findViewById(R.id.textView1);
TextView rDate = (TextView) v.findViewById(R.id.text4);
TextView rLeftLabel = (TextView) v.findViewById(R.id.text5);
TextView rLeft = (TextView) v.findViewById(R.id.text6);
ImageView callPhone = (ImageView) v.findViewById(R.id.Call_Pharmacy);
pName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
pa.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
rDateLabel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
rDate.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
rLeftLabel.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
rLeft.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
goToPDetails();
}
});
callPhone.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Some Code
}
});
}
All those onClick listeners (those on single sub-views of one ListView element) probably shouldn't be here in the onListItemClick method, but in the getView method of your Adapter instead (with proper use of the convertView argument).
The way you do it seems quite wrong, maybe your onListItemClick method isn't even needed if you correctly implement the various onClick listeners at the right place.
Using an xml based layout for your list item is key here. Set each individually clickable View with two attributes android:clickable="true" and android:onClick="<your click handler>" the method will need to be implemented with this signature: public void <your click handler> (View v) {...} in your Activity. A side note is that you'll have to make a design decision to implement a click handler to overlap handling (one click hanlder for more than one View) or a single view handler per View, the former is best for when click are substantially similar in function and the latter is when they are different.
The next step is to implement the click handler, the key here is to use ListView.getPositionForView(View v) so you can associate the row, the data, and the View clicked.
Don't forget to implement ListActivity.onListItemClick() as a catch-all for clicking on the root layout of the list item and as a catch-all for Views that don't have their own onClick handler set.
The above technique will have good performance and makes use of several Android API's to speed your development.
If you decide to implement the listeners in code, please study getView() closely (as darma mentioned) and for the sake of performance (if you have several items in your list) reuse the click listeners with the above discussion about how to associate the data and row.

Categories

Resources