I have 3 fragments and one activity. These fragments define an interface for communicating a result to the activity.
This interface is initialized in onAttach() and set to null in onDetach(). However, when activity is destroyed and recreated on rotation, the interfaces are set to null and when they are invoked, it results in a NullPointerException.
Here is my code for the fragments and the activity.
MainActivity.java
package com.gianfranco.rsa.view;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.gianfranco.rsa.R;
import com.gianfranco.rsa.view.fragment.InputKeySizeFragment;
import com.gianfranco.rsa.view.fragment.InputPlainTextFragment;
import com.gianfranco.rsa.view.fragment.RSADetailsFragment;
public class MainActivity extends AppCompatActivity implements InputKeySizeFragment.OnKeySizeListener,
InputPlainTextFragment.OnMessageListener, RSADetailsFragment.OnClickHomeListener {
private InputKeySizeFragment inputKeySizeFragment;
private InputPlainTextFragment inputPlainTextFragment;
private RSADetailsFragment rsaDetailsFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
inputKeySizeFragment = new InputKeySizeFragment();
inputPlainTextFragment = new InputPlainTextFragment();
rsaDetailsFragment = new RSADetailsFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.main_container, inputKeySizeFragment)
.addToBackStack(null)
.commit();
}
}
@Override
public void onKeySizeSelected(int keySize) {
getSupportFragmentManager().beginTransaction()
.add(R.id.main_container, inputPlainTextFragment)
.addToBackStack(null)
.commit();
}
@Override
public void onMessageEntered(String message) {
getSupportFragmentManager().beginTransaction()
.add(R.id.main_container, rsaDetailsFragment)
.addToBackStack(null)
.commit();
}
@Override
public void onClickHome() {
getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
getSupportFragmentManager().beginTransaction()
.add(R.id.main_container, inputKeySizeFragment)
.addToBackStack(null)
.commit();
}
}
InputKeySizeFragment.java
package com.gianfranco.rsa.view.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import com.gianfranco.rsa.R;
public class InputKeySizeFragment extends Fragment {
private Spinner keySizeSpinner;
private Button buttonNext;
private ArrayAdapter<Integer> adapter;
private OnKeySizeListener listener;
@FunctionalInterface
public interface OnKeySizeListener {
void onKeySizeSelected(int keySize);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnKeySizeListener) {
listener = (OnKeySizeListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_input_key_size, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
keySizeSpinner = view.findViewById(R.id.spinner_key_size);
buttonNext = view.findViewById(R.id.btn_next);
Integer[] bits = new Integer[]{64, 128, 256, 512, 1024, 2048};
adapter = new ArrayAdapter<>(getActivity(), R.layout.support_simple_spinner_dropdown_item, bits);
adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
keySizeSpinner.setAdapter(adapter);
buttonNext.setOnClickListener(v -> {
int keySize = (Integer) keySizeSpinner.getSelectedItem();
listener.onKeySizeSelected(keySize);
});
}
@Override
public void onDestroyView() {
keySizeSpinner = null;
buttonNext = null;
adapter = null;
super.onDestroyView();
}
@Override
public void onDetach() {
listener = null;
super.onDetach();
}
}
InputPlainTextFragment.java
package com.gianfranco.rsa.view.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import com.gianfranco.rsa.R;
public class InputPlainTextFragment extends Fragment {
private EditText editTextMessage;
private Snackbar snackbar;
private Button buttonNext;
private OnMessageListener listener;
@FunctionalInterface
public interface OnMessageListener {
void onMessageEntered(String message);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMessageListener) {
listener = (OnMessageListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_input_plain_text, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
editTextMessage = view.findViewById(R.id.et_message);
buttonNext = view.findViewById(R.id.btn_details);
buttonNext.setOnClickListener(v -> listener.onMessageEntered(editTextMessage.getText().toString()));
}
@Override
public void onDestroyView() {
editTextMessage = null;
buttonNext = null;
super.onDestroyView();
}
@Override
public void onDetach() {
listener = null;
super.onDetach();
}
}
RSADetailsFragment.java
package com.gianfranco.rsa.view.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import com.gianfranco.rsa.R;
public class RSADetailsFragment extends Fragment {
private TextView pValue;
private TextView qValue;
private TextView nValue;
private TextView zValue;
private TextView dValue;
private TextView eValue;
private TextView encryptedValue;
private TextView decryptedValue;
private Button buttonHome;
private OnClickHomeListener listener;
@FunctionalInterface
public interface OnClickHomeListener {
void onClickHome();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnClickHomeListener) {
listener = (OnClickHomeListener) context;
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_rsa_details, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
pValue = view.findViewById(R.id.tv_pValue);
qValue = view.findViewById(R.id.tv_qValue);
nValue = view.findViewById(R.id.tv_nValue);
zValue = view.findViewById(R.id.tv_zValue);
dValue = view.findViewById(R.id.tv_dValue);
eValue = view.findViewById(R.id.tv_eValue);
encryptedValue = view.findViewById(R.id.tv_encrypted_value);
decryptedValue = view.findViewById(R.id.tv_decrypted_value);
buttonHome = view.findViewById(R.id.btn_home);
buttonHome.setOnClickListener(v -> listener.onClickHome());
}
@Override
public void onDestroyView() {
pValue = null;
qValue = null;
nValue = null;
zValue = null;
dValue = null;
eValue = null;
encryptedValue = null;
decryptedValue = null;
buttonHome = null;
super.onDestroyView();
}
@Override
public void onDetach() {
listener = null;
super.onDetach();
}
}
And this is the error message
03-10 00:03:16.243 31676-31676/com.gianfranco.rsa E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.gianfranco.rsa, PID: 31676
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:392)
at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:381)
at com.gianfranco.rsa.view.MainActivity.onKeySizeSelected(MainActivity.java:39)
at com.gianfranco.rsa.view.fragment.InputKeySizeFragment.lambda$onViewCreated$0$InputKeySizeFragment(InputKeySizeFragment.java:58)
at com.gianfranco.rsa.view.fragment.InputKeySizeFragment$$Lambda$0.onClick(Unknown Source)
at android.view.View.performClick(View.java:4819)
at android.view.View$PerformClick.run(View.java:20152)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5562)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:968)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:763)
Is there anything I'm missing or doing wrong? Please, let me know.
Add this line in your activity manifest
android:configChanges="keyboardHidden|orientation|screenSize"
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.