I'm using a Master / Detail flow (not the default one), so I have one fragment that contains the stuff of the RecyclerView and when I click on a item I see on other fragment the detail of that item, it works, but now I want to delete this item from the detail fragment, and when I click on delete it refreshes and then notifydatasetchanged.
What's the problem? I have the Adapter on my ListFragment and on my DetailFragment I only can delete the item from my SQLite nothing else, I'd like to refresh the list.
Activity -- Where I create the listFragment
Fragment1 -- ListFragment (RecyclerView, Adapter, Sqlite(For fetch products))
Fragment2 -- DetailFragment (Sqlite(to delete item))
Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
if(savedInstanceState == null){
Fragment list = new ListFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.list,list).commit();
}
}
On my ListFragment I have those attributes
private SQLiteAdapter sqliteAdapter;
private Context mContext;
private Adapter adapter;
private RecyclerView recyclerView;
private List<Product> data;
Then I put the data with a method that open the sqliteAdapter and then fetch all products and then closses the connection.
On my DetailFragment I have the SQLite object to get the product sent from the adapter (id product) and then show info about this product.
Now I can delete an object, but it's not refreshing from ListFragment, I'm wondering where to put this SQLite object on Activity or in both fragments is ok
It sounds like you are only deleting the item from your database. You also need to delete it from the adapter's list or other data structure.
Related
I want to add list of items to my cart and when user taps the cart option all those items selected from different activities of the app loads to the cart. Intents start a new activity and I don't want to start the cart activity every time user adds any item. I've used shared preferences but it is updating the same list item again and again or crash the app. I am new to android, any help will be appreciated . Thanks in advance.
public class NewClass extends Activity {
private ListView mCompleteListView;
private List<String> mItems;
private CompleteListAdapter mListAdapter;
private String myData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_class);
SharedPreferences sharedPreferences = getSharedPreferences("MyData",
Context.MODE_PRIVATE);
myData = sharedPreferences.getString("SharedData", "none");
initViews();
addItemsToList();
mItems = new ArrayList<String>();
mListAdapter = new CompleteListAdapter(this, mItems);
mCompleteListView.setAdapter(mListAdapter);
}
private void initViews() {
mCompleteListView = (ListView) findViewById(R.id.completeList);
}
private void addItemsToList() {
mItems.add(myData );
mListAdapter.notifyDataSetChanged();
}
}
I just want to populate list items of cart from several other activities without starting that activity.
this isn't the best way of doing that, read about viewmodel,
dialogfragment and room.
long story short you want to create a database that holds the data from the cart. (room) and than you would be able to get that any where in the app.
or
you can hold the data as a var in a viewmodel, and communicate with a dialogfragment (the cart) by getting the viewmodel of the activity.
all the best :)
First fragment
private void initRecyclerView() {
Main.musicList = Main.songs.songs;
if ((Main.musicList != null) && (!Main.musicList.isEmpty())) {
// Connects the song list to an adapter
// (Creates several Layouts from the song list)
allSongsAdapter = new AllSongsAdapter(getActivity(), Main.musicList);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerViewSongs.setLayoutManager(linearLayoutManager);
recyclerViewSongs.setHasFixedSize(true);
recyclerViewSongs.setAdapter(allSongsAdapter);
}
}
In the first fragment i have a recyclerview which displays a list with all songs found on the device and i have an option to delete a song which changes the data in my arraylist Main.musicList by rescanning all songs on the device.
So all my other arraylists in my app still have a reference to that deleted song.
So how can i call notifySetDataChanged on all recyclerview adapters in other fragments when i delete an item in the first fragment?
Use ViewModel in your Activity which holds these fragments.
Wrap your song list in LiveData object. This can be observed by all
of your fragments depending on their lifecycle (when the fragment is
in OnResumed state, it will be automatically notified when your list
has changed)
In related fragment start to observe LiveData and on
change update your adapter.
Related topics:
https://developer.android.com/topic/libraries/architecture/livedata
https://medium.com/androiddevelopers/viewmodels-and-livedata-patterns-antipatterns-21efaef74a54
Hope I could help you.
The easy way will be to use BroadcastReceiver. try this answer
You can use EventBus to trigger the method, by which reyclcer view adapter will be notified
I'm having trouble with restoring state of a View inside a ViewPager. The content of the ViewPager is a view extending FrameLayout.
The problem is the FrameLayout.onRestoreInstanceState() is not being called if added programmatically into the ViewPager
Here's the code of my Activity.java
private ViewPager vPager;
private MainPagerAdapter mAdapter;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
setContentView(R.layout.activity_layout);
// all the findViewById stuff
CustomView cv1 = new CustomView(this);
CustomView cv2 = new CustomView(this);
cv1.setId(R.id.custom_view_id_1);
cv2.setId(R.id.custom_view_id_2);
mAdapter = MainPagerAdapter();
mAdapter.addView(cv1);
mAdapter.addView(cv2);
vPager.setAdapter(mAdapter);
}
MainPagerAdapter is a class from the accepted answer of this question
Source code for CustomView.java
#Override
protected Parcelable onSaveInstanceState() {
Log.d(TAG, "onSaveInstanceState() called");
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
Log.d(TAG, "onRestoreInstanceState() called");
}
Here's my findings so far:
onSaveInstanceState() will be called but onRestoreInstanceState() is not
When I tried to add the View directly to the root of the Activity, it calls both functions.
I found out that Activity's onRestoreState function will be called before the ViewPager calls the adapter's instantiateItem() function. So when the activity restore its state, the ViewPager doesn't have any children yet, thus the savedState doesn't belong to anyone
So I figure out that I need to make one of two things to work:
Make sure the ViewPager instantiate the item before trying to restore the state, or
Calls the CustomView's onRestoreInstanceState() manually.
I somehow managed to make option number 2, but is there any way to do option number 1?
If I understood your question, you can save your ViewPager items state using mPage.setOffscreenPageLimit(4); 4 is the number of my Fragments inside ViewPager.
I have an activity with a viewPager inside of it, and a static ArrayList of integers that I am shuffling using Collections.shuffle(list) in the activity's onCreate method, this viewPager's fragments are using the ArrayList in parent activity.
The problem is that whenever a new fragment instantiated of the viewPager the onCreate method of parent activity is called, and I don't want that to happen because I want the list to have the same data in all fragments and not reshuffled. Do fragments call the onCreate method of their parent activities everytime there is a new instance? if Yes how can I work around this to keep the list from shuffling every time?
CODE:
Activity Code:
public static final ArrayList<Integer> IDs = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
IDs.add(0);
IDs.add(1);
IDs.add(2);
Collections.shuffle(IDs);
setContentView(R.layout.activity_walkthrough);
pager = (ViewPager) findViewById(R.id.pager);
adapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
pager.setAdapter(adapter);
Fragment Code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = (View) inflater.inflate(
R.layout.fragment_walkthrough, container, false);
final TypedArray imgs = getResources().obtainTypedArray(R.array.walkthrough_images);
ImageView imageView = (ImageView) v.findViewById(R.id.image);
if (page == 0) {
imageView.setImageResource(imgs.getResourceId(Walkthrough.IDs.get(0), 0));
} else if (page == 2) {
imageView.setImageResource(imgs.getResourceId(Walkthrough.IDs.get(1), 0));
} else {
imageView.setImageResource(imgs.getResourceId(Walkthrough.IDs.get(2), 0));
}
return v;
}
Now I want the ArrayList "IDs" to always have the same data and order when ever I instantiate a new fragment but it is not working, every time I create a new fragment the method onCreate gets recalled and a reshuffle happens!
Fragments are added to activity and therefore fragments get affected by activity.
Activity can cause calling any fragment callback method, but fragment can't
The lifecycle of the activity in which the fragment lives directly affects the lifecycle of the fragment.
For example, when the activity receives onPause(), each fragment in the activity receives onPause().
Fragments have a few extra lifecycle callbacks, however, that handle unique interaction with the activity in order to perform actions such as build and destroy the fragment's UI.
These additional callback methods are like onAttach(), onCreateView(), etc.
It'll clears the somewhat relation between fragment and activity.
Thanks
How do I add items to a list dynamically when button is clicked? The text is added to the listView. At the moment it only adds one item to the list view, and when you try to add another it just changes the already added item in the list.
Here is my code:
This is the button on click for activity A that gets the text:
schedule.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
AddSchedule();
Intent i = new Intent(ScheduleActivity.this, MainActivity.class);
String str = event_name.getText().toString();
i.putExtra("myExtra", str);
startActivity(i);
}
});
Then in activity B it gets the text from activity B but only adds the
Final ListView listView = (ListView) findViewById(R.id.listView);
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(adapter);
Intent i = getIntent();
if (i.hasExtra("myExtra")) {
list.add(i.getStringExtra("myExtra"));
adapter.notifyDataSetChanged();
}
You only see one item in the new activty's list, since that Activity is created each time via startActivity(Intent) (I suppose). So each time open Activity B, it's a new instance. The arraylist is empty.
You need to keep track of the items clicked in Activity A and send the whole list to Activity B, every time. Activity B should get the complete list in the intent and create the gui-list.
Make your class implement Parcelable or Serializable (slower).
Inside activity B you should include the following:
#Override
public void onSaveInstanceState(Bundle out){
super.onSaveInstanceState(out);
out.putStringArrayList(key, list);
}
"key" is a final String you have defined in Activity's B member variables.
This will make sure your list is saved before being destroyed (For more, read about Activity Lifecycle. Now, you also need to restore in whenever the activity is created. You can do that in onCreateView like so:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//restore the contents of your list
if (savedInstanceState!=null)
list=savedInstanceState.getStringArrayList(key);
/* initialize the adapter and set it to the list */
//also add the new item from activity A
Intent i = getIntent();
if (i.hasExtra("myExtra")) {
list.add(i.getStringExtra("myExtra"));
adapter.notifyDataSetChanged();
}
}
General note, instead of adding to the list and afterwards notifying the adapter, you can instead add your items directly to the adapter. The adapter will automatically update your list.
Edit: Yes, your list should be a member variable because it needs to be accessed in 2 methods.