I would like to tag this question with both C# and Java; for Java programmers, I'm sure you can understand the C# code here easily, they are very similar.
I've encountered many weird problems since knowing how to program and this is one of the weirdest problems, it is surely a problem of the Android engine and API.
Firstly I would like to shortly describe how strange it is. Can you think of any situation in which the call setContentView
does not do anything? No exception is thrown, the content view of the Activity is simply not changed to what I want (even passing a null
value makes nothing happen).
In fact I've not tried testing some other scenarios to reproduce the problem. But the scenario I'm going to describe here should reproduce the problem easily.
You need a simple custom Fragment
where you load a simple layout having a simple Button
. Now in the onCreateView
callback, you inflate the layout, hookup the Click
event of the Button
to fire another exposed event via the custom Fragment.
The Fragment
has RetainInstance
set to true
. Now in the MainActivity
, you declare a static field of the custom Fragment
. The Fragment
is created only once (by checking against null
) in the OnCreate
callback of the MainActivity
. We hook up the exposed click event of the custom Fragment
with a handler which simply shows the new content using SetContentView
.
The code works fine without screen rotation first. But after screen rotation, the SetContentView
simply does nothing and there is no exception. It sounds like the click event is not fired due to something BUT in fact it's still fired OK and the SetContentView
is actually called (I'm sure about this, because I debugged it by setting a breakpoint there).
Here is the code:
The main layout: (this is named as Main.axml
)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
The custom Fragment:
public class CustomFragment : Fragment {
//the click event
public event EventHandler ButtonClick;
void onButtonClick(EventArgs e){
var handler = ButtonClick;
if(handler != null) handler(this,e);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState){
//we can even use a simple layout as a Button.
var button = new Button(parent.Context);
button.Click += (s,e) => {
onButtonClick(EventArgs.Empty);
};
return button;
}
}
The MainActivity:
[Activity(Label = "Hello", MainLauncher = true]
public class MainActivity : AppCompatActivity {
//the static custom Fragment
static CustomFragment frag;
protected override void OnCreate(Bundle bundle){
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
//this ensures that the code inside if block is run just once
//between screen rotations
if(frag == null){
frag = new CustomFragment(this);
frag.RetainInstance = true;
frag.ButtonClick += (s,e) => {
//whatEverView here is any View, layout resource id
//or even null value.
SetContentView(whatEverView);
};
//load the fragment into the container in the Main layout
var ft = FragmentManager.BeginTransaction();
ft.Replace(Resource.Id.container, frag);
ft.Commit();
}
}
}
Well that's all setup to reproduce the strange problem.
As I described above, the code runs just fine without rotating the screen. But after rotating the screen, SetContentView
does nothing although it is surely called (I know for sure by setting break point on the call).
One more thing which I think is also important is all calls after SetContentView
seem not to be called (because the break points set on them are not reached, after SetContentView
run, it's like that there was a return
interrupting the code there). No exception and the app is not crashed, just runs normally after that (clicking the Button again will again call the SetContentView
).
It's very weird and there must be something wrong internally happening that I've not known of. Reading the source code is not my strength partly because I'm still fairly new to Android programming.
You may need to try replicating the problem on your own machine to understand this issue.
Finally the code is run on Kitkat and Marshmallow Android OS (run by Visual Studio Emulator).