parentActivityName forces onCreate - java

In my Android manifest, I am specifying a parentActivityName in order to utilise the back button displayed in the activity.
I find this however re-calls onCreate of the previous activity, in which I do several network calls and set up a recycler view widget.
This causes the screen to refresh entirely, I'd like to avoid this and deal with the recyclerview and what new content to display and delete to ensure the user flow is not jolted.
I currently set my application up in onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_container_list);
final SwipeRefreshLayout swiperefreshContainerListRecyclerView = (SwipeRefreshLayout) this.findViewById(R.id.swiperefresh_container_list_recyclerview);
swiperefreshContainerListRecyclerView.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
refreshContainerList();
}
}
);
// Get a handle on our RecyclerView for interactin and setup
containerListRecyclerView = (RecyclerView) findViewById(R.id.container_list_recyclerview);
// Grab a new LayoutManager
containerListLayoutManager = new LinearLayoutManager(this);
// Grab a new adapter
List<ContainerModel> containers = new ArrayList<>();
containerListRecyclerAdapter = new ContainerListRecyclerViewAdapter(containers, this);
// Better performance as the size of our RecyclerView does not change
containerListRecyclerView.setHasFixedSize(true);
// Attach our LayoutManager to our RecyclerView
containerListRecyclerView.setLayoutManager(containerListLayoutManager);
// Wire up adapter for RecyclerView
containerListRecyclerView.setAdapter(containerListRecyclerAdapter);
cAdvisorService = new CAdvisorService();
cAdvisorService.fetchDataFromService(context, containerListRecyclerAdapter);
System.out.println("Running onCreate!");
}
I already have logic within my cAdvisorService to deal with removing and adding items into the RecyclerView.
How do I deal with the fact that onCreate is called each time, forcing new instances of my RecyclerView and cAdvisorService?

There way to achieve this by declaring your parent activity in your Android manifest as
android:launchMode="singleTop"
, see more at: How can I return to a parent activity correctly?

Related

how to add an item to a listView whithout changing other Items

I'm beginner in android and i want to add an item to a ListView when i click on a button.
but when i do that , the ListView restarts and all the previous changes i made disappear.
how can i save the previous state of the ListView.
This is the MainActivity :
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listMarks = (ListView) findViewById(R.id.list_marks);
btn_add = (Button) findViewById(R.id.btn_add);
final Mark mark = new Mark("", "", "", "");
final ArrayList<Mark> marks = new ArrayList<Mark>();
marks.add(marks.size(), mark);
adapter = new MarkLitViewAdapter(MainActivity.this, marks);
listMarks.setAdapter(adapter);
btn_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
marks.add(mark);
adapter.notifyDataSetChanged();
}
});
}
I made this changes but when click on add button an item is being add but previous changes disappear this is when i click on the add button
First off, I strongly suggest you use RecyclerView instead of ListView, if you aren't already. It's a categorically better version of ListView.
The function you are looking for is notifyItemInserted.
I wrote up a very simple example in Kotlin (also suggested learning if you want to continue in Android development, since it's the officially supported language now.)
The relevant snippet is below. Create an addItem function in your adapter which uses notifyItemInserted:
fun addItem(value: String) {
items.add(value)
notifyItemInserted(items.size)
}
And then in your button OnClickListener call that adapter function to add a new item.
Instead of doing adapter.insert(mark, marks.size()); you can use the adapter.notifyDataSetChanged(); functionality. Remove the final from here final ArrayList<Mark> marks = new ArrayList<Mark>(); and insert your Mark into this ArrayList and then do adapter.notifyDataSetChanged() inside the OnClickListener

Adding checkboxes into a ListView

Hello I'm currently trying to make my first app on android and I've gotten some problems. I'm trying to make a todo-list app so want some kind of input to be transformed into checkboxes. I've made it work with radio buttons using radioGroup. But when using Checkboxes with ListView it just doesn't work.
Here's my code:
public class MainActivity extends AppCompatActivity {
EditText t;
ListView listView;
ArrayList<CheckBox> checkList = new ArrayList<>();
int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void add(View view){
t = findViewById(R.id.input);
String s = t.getText().toString();
CheckBox check = new CheckBox(this);
checkList.add(check);
listView = findViewById(R.id.list);
checkList.get(i).setText(s);
listView.addView(checkList.get(i));
i++;
t.setText("");
}}
The app crashes saying something about adapterView
You're unfortunately doing something wrong here. You are trying to add your view to Listviews on
listView.addView(checkList.get(i));
This is not the correct way to use ListViews. You have to use an adapter. The adapter would need to provide data for the listview to load.
Please have a look at this tutorial for how to use listviews.
Below is a summary of the steps to use a listView correctly.
Create a new layout file (say custom_cell.xml) inside your layouts folder.
Insert a checkbox inside your custom_cell.xml and place an Id which you can use later to identify the checkbox
Create an adapter for your listview
Override the getView method
Inside the getView method, inflate a new cell using the custom_cell.xml or reuse an existing cell if provided
Reference the Checkbox by using the Id you provided in the custom_cell.xml file

App crashes when setting background colour

Every time I run my app it crashes giving me a nullpointerexception, I want to programatically change my background depending on the scenario, here is my code:
Main Activity:
public class Activity extends AppCompatActivity {
ConstraintLayout layout;
String messageSafe = "Item is Safe for Consumption";
String messageUnSafe = "Item is NOT Safe for Consumption";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_information);
layout = new ConstraintLayout(this);
if (matched.length == 0) {
layout.setBackgroundResource(R.drawable.background_safe);
setContentView(layout);
changeColor("#00FF00");
messageView.setText(messageSafe);
}
else{
layout.setBackgroundResource(R.drawable.background_unsafe);
setContentView(layout);
changeColor("#FF0000");
messageView.setText(messageUnSafe);
}
ListView listContains = (ListView) findViewById(R.id.lvItemsFound);
ArrayAdapter<String> contains = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, foundItems);
listContains.setAdapter(contains);
ListView listRestricted = (ListView) findViewById(R.id.lvItemsRestricted);
ArrayAdapter<String> found = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, matched);
listRestricted.setAdapter(found);
}
You are losing reference to your old view because you changed the layout to a new ConstraintLayout object. This means you now don't have your ListView objects and other items in your XML because that View is gone. It's not the ContentView anymore. If you want to work on the existing layout, you need to give the root view an ID.
<constraintlayout android:id="#+id/container" ... />
Then you can reference that ID with findViewById(R.id.container) and use the object you get from it to change your background like you are doing.
Try this:
1. Give your root view an ID
2. Set a ConstraintLayout object with ConstraintLayout layout = findViewById(R.id.container) (Note: You can call it anything, not just container, I am just going off my example from above, since I gave it the ID 'container')
3. call setBackgroundResource() like you are doing.
4. No need to call setContentView() again, this was set in the beginning, and you do not want to reset it to a new view you just constructed like you were initially doing.
5. You shouldn't crash when trying to call setAdapter() to your ListView now because you don't have a reference to an object that isn't in your content view.
layout = (ConstraintLayout)findViewById(R.id.container);
if (matched.length == 0) {
layout.setBackgroundResource(R.drawable.background_safe);
changeColor("#00FF00"); //assuming this is some local function?
messageView.setText(messageSafe);
}
else{
layout.setBackgroundResource(R.drawable.background_unsafe);
changeColor("#FF0000");
messageView.setText(messageUnSafe);
}
You are trying to set the background by replacing the view of your activity (this is what setContentView() does). This causes a null pointer exception later because the old layout (defined in the XML) has been replaced, so your list view no longer exists.
Instead, you should get a reference to the existing root view (the ConstraintLayout, although if you're just setting background you can just reference it as a View, no need to be so specific), and set the background on it, like so:
findViewById(R.id.container).setBackgroundResource(R.drawable.unsafe);
You'll also need to give the containing layout an id in the existing layout XML:
<android.support.constraint.ConstraintLayout
android:id="#+id/container"
... etc.

Android - How to restore state of ViewPager's items

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.

Does fragment call the onCreate method of parent activity?

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

Categories