First of all I am using support library (android-support-v4.jar) for using fragments.
I have an activity with layout containing a fragment in it. So when the activity starts it calls onCreateView method of my fragment. In this method I inflated a layout( containing a linearlayout and a listview in it ) and return that inflated view.
So when the activity starts it loads my listview and call a webservice and in response of the webservice loads the data on the listview.
Every thing works perfect as expected. But the problem is when I press the back button and restart the activity then it doesn't attach my fragment to the activity and throws IllegalStateException when I try to call getActivity(). And also throws NullPointerException when I try to call getView() method of my fragment.
One more thing to mention that when i see the view hierarchy from the TraceView tool then it shows my fragment views there.
Please help me!
I figured out the problem and hence solved it as well.
I was using the Observer interface to get the response from the web service. So when i started the activity first time then I added(or registered) my fragment activity to the Observable class and received the response but forgot to remove(or de-register) my fragment object when it destroyed. So when the activity and fragment restarts it again add my fragment object to the Observable class so now Observable class now has two instances of fragment first one has been destroyed and the current fragment and web service is called and it first respond with the destroyed fragment and that time it will crash. So i removed the fragment instance from the Observable class in the onDestroy method of fragment and it working now.
So the problem is not with the fragments but with the multiple instances of my fragment.
Related
I have a fragment that implements Recycler View with switches. RecyclerView sets id for every switch in id+=1 way. The problem is I can get nothing from these IDs as soon as calling throws NullableException. I understand that I have to call it correctly from parent, but I don`t get how to do it correctly.
There is the structure of code:
Fragment with ConstraintLayout(R.id.settingsScreen) -> RecylerView(R.id.recyclerView), that creates LinearLayouts(R.id.settingLayout) with switches(R.id.switch).
class ViewHolder{
val l : LinearLayout = view.findViewById(R.id.settingLayout)
}
if (holder.l.findViewById<SwitchCompat>(1100).isActivated){..}
throws java.lang.NullPointerException: Attempt to invoke virtual method 'boolean androidx.appcompat.widget.SwitchCompat.isActivated()' on a null object reference
It is very fragile to create view IDs yourself like this. They could easily collide with IDs generated by the Android build. So if you create IDs, you should be using ViewCompat.generateViewId() to do it safely.
But findViewById is something you generally want to avoid in the first place. It is slow. That's why View Binding is provided, to cache the views so you don't have to keep searching for them.
I highly recommend storing your Views in a collection instead of assigning them IDs. Then you can efficiently pull them from the collection when you need them. You just need to be sure the collection will be garbage collected when you're done with the views (don't create a collection that will outlive the screen the views are on).
You can get the view by using itemView property
Not sure of you are trying to do when you mean custom id.
You can get all views inflated by viewHolder with itemView.
this property is given to ViewHolder after you pass view as parameter in ViewHolder constructor, than ViewHolder will inflate views according with their id's.
than you can get view inside ViewHolder by:
itemView.findViewById<LinearLayout>(R.id.settingLayout)
itemView.findViewById<SwitchCompat>(R.id.switch)
You can look to see more options in google docs
If these are not what you asked for please let me know
I have an issue with the data observation and the fragment backstack on a single activity application.
For example, I have parent fragment A which will observe data from viewmodel and fill to ExitText. User can change the information in the EditText. Fragment A can navigate to fragment B and listen to B result by using setFragmentResultListener.
The problem is, when popBackStack from B, the changed data on fragment B will be revert to data from viewmodel because I observed the data in onCreateView.
Is there anyway I can retain the changed data from fragment A after popBackStack from fragment B?
Thank you!
You can use SharedViewModel since both fragments share same activity. In this way view model does not die and you can use the data.
Offical doc:
https://developer.android.com/topic/libraries/architecture/viewmodel#sharing
I am writing a very basic 3D modelling program. I've used LWJGL to render my objects and JavaFX to provide an user interface in a separate window, new thread.
As I saw JavaFX likes to take control over the application, but in my case this was not an option. I tried to pass my already created scene graph to the JavaFX controller class, but I didn't find a way doing this properly.
It's seems to be impossible to pass anything from outside into the main JavaFX class. The start method loads the layout from an FXML file with reflection magic, but this method is called in the constructor, therefore variables are not initialized. Defining a new constructor with parameters throws an exception (class cannot be initialized).
After struggling many hours, I gave up, I've decided to create a new scene graph in the JavaFX controller and created a getter method to it.
public class Toolbox extends Application implements Runnable {
private ToolboxLogic logic = new ToolboxLogic(); //controller, the scene graph is instantiated
...
public SceneGraph getSceneGraph() {
return logic.sceneGraph; // returns the scene graph
}
}
Not a beautiful solution, but it shall work, I said. But it doesn't.
I tried to load a file in two locations:
with code written in the LWJGL renderer
with buttons, calling a method in the controller
If I load a file from the renderer, my objects show up on the screen, but I cannot navigate with the buttons, only the root node appears in the scene graph.
If I load a file from the user interface, I can navigate on the tree, but it doesn't show up in the renderer.
It seems like here
return logic.sceneGraph;
Java would have done a deep copy instead of returning a pointer, and each part of my program is working with its own version of the scene graph.
What is a problem, and how can I make it work properly?
Thank you!
OK, I got it working by setting the scene graph static. Strange! Now, I'm really curious, why it behaves like this.
When is executed the onDraw method of a DynamicForm exactly?
When I first load my page (a puremvc.Mediator page) and draw my DynamicForm with an onDraw method, I enter in this onDraw method. Then I destroy the view component, remove the Mediator from the Facade, and re-load the page. DynamicForm is being created again, the viewComponent too, but I don't enter in the onDraw method. Just as if the object has already been drawn! But the thing is it was destroyed, its parent too, and the parent of the parent, too.
What could be the problem?
OK, I got it.
The thing is that I use PUREMVC Mediator and Notification. On the first load, everything's good as the async method that returns data for DynamicForm C is sending the successful notification AFTER I have already created the VLayout B, and thus the addMember method adds and displays the DynamicForm C.
On the second load, I use the data that has already been gathered from DB, so no async method is being processed and the notification arrives BEFORE I create VLayout B, so basically the DynamicForm C is NOT being drawn.
My solution : I reordered some lines of code to make sure I always call the method that sends data via Notification (whether from DB or stocked) AFTER of the page creation.
I have subclassed RMMessageComposeViewController : MFMessageComposeViewController. The extra functionality that I'm aiming for is for the MFMessageComposeViewController to be able by itself to present a new message compose controller (over itself).
So I should from one RMMessageComposeViewController instance present a new one. The message result from the new instance should be sent to the parent (or "old" one). So I suppose I need to set the parent message compose controller as the delegate when I'm creating the child ("new" one).
Could someone please help me think this out, what instance variables I need to add (parents, children?) How to setup the child message compose controller?
From the docs:
The message composition interface itself is not customizable and must not be modified by your application. In addition, after presenting the interface, your application is unable to make further changes to the SMS content.
What you're trying to do there is explicitly not supported because of security concerns: It would make it easy for an application to forge messages. While you can probably push a view on top of it, I suspect your app would get rejected from the App Store for doing it.
I wouldn't be surprised if MFMessageComposeViewController prevents an application from creating more than one instance at a time, though I haven't confirmed this.