Cannot setText() of an EditText field (Android) - NullPointerException [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
textView setText() NullPointerException
(3 answers)
Closed 5 years ago.
When I try to setText() on an EditText I keep getting this error, I can't see where I'm going wrong. I'd like to understand the logic behind this error. I'm sure it's something small but it's really bugging me now.
01-25 10:20:44.267
14325-14325/com.example.gregsquibbs.greg_squibbs_todoapp3
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.gregsquibbs.greg_squibbs_todoapp3, PID: 14325
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.gregsquibbs.greg_squibbs_todoapp3/com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.EditText.setText(java.lang.CharSequence)' on a null
object reference
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual
method 'void android.widget.EditText.setText(java.lang.CharSequence)'
on a null object reference
at
com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoFragment.setMessage(EditTodoFragment.java:56)
at
com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity.onCreate(EditTodoActivity.java:41)
at android.app.Activity.performCreate(Activity.java:6975)
at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892) 
at android.app.ActivityThread.-wrap11(Unknown Source:0) 
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593) 
at android.os.Handler.dispatchMessage(Handler.java:105) 
at android.os.Looper.loop(Looper.java:164) 
at android.app.ActivityThread.main(ActivityThread.java:6541) 
at java.lang.reflect.Method.invoke(Native Method) 
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
This is where I create the etMessage and use setText()
public class EditTodoFragment extends Fragment implements EditTodoContract.View {
private EditTodoContract.Presenter presenter;
private EditText etMessage;
public EditTodoFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_todo_fragment, container, false);
System.out.println("Step 2 - Fragment check");
etMessage = (EditText) view.findViewById(R.id.etMessage);
return view;
}
public void setPresenter(EditTodoContract.Presenter todoPresenter) {
this.presenter = todoPresenter;
}
public String getMessage() {
String message = etMessage.getText().toString();
return message;
}
public void setMessage(String message) {
etMessage.setText(message);
}
}
Here is the XML file
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.gregsquibbs.greg_squibbs_todoapp3.EditTodo.EditTodoActivity">
<EditText
android:id="#+id/etMessage"
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:background="#drawable/rect"
android:ems="10"
android:gravity="top"
android:inputType="textShortMessage" />
<Button
android:id="#+id/bSave"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Save"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:onClick="saveButtonClicked"
android:layout_gravity="center_horizontal|bottom"
/>
Here is where setMessage() gets called in the activity
public class EditTodoActivity extends AppCompatActivity {
private String message;
private int position;
private EditTodoFragment editTodoFragment;
private EditTodoPresenter editTodoPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_todo_activity);
System.out.println("Step 1");
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.contentFrameContainer);
if (fragment == null){
editTodoFragment = new EditTodoFragment();
fm.beginTransaction()
.add(R.id.contentFrameContainer, editTodoFragment)
.commit();
editTodoPresenter = new EditTodoPresenter(editTodoFragment);
}
message = getIntent().getStringExtra(IntentConstants.INTENT_MESSAGE_DATA);
position = getIntent().getIntExtra(IntentConstants.INTENT_ITEM_POSITION, -1);
editTodoFragment.setMessage(message);
}
public void saveButtonClicked(View v) {
if(editTodoFragment.getMessage().equals("")) {
} else {
String changedMessage = (editTodoFragment.getMessage());
Intent intent = new Intent();
intent.putExtra(IntentConstants.INTENT_CHANGED_MESSAGE, changedMessage);
intent.putExtra(IntentConstants.INTENT_ITEM_POSITION, position);
finish();
}
}
}
Edit: On this line in the fragment
etMessage = (EditText) view.findViewById(R.id.messageField);
When I hover over the casting (EditText) it says
Casting 'view.findViewById(R.id.messageField)' to 'EditText' is redundant less... (⌘F1)
This inspection reports unnecessary cast expressions.
I don't know whether that has anything to do with it or not.

There is no garrenty that editTodoFragment.setMessage(message); will be called after your EditText initialized by this line
etMessage = (EditText) view.findViewById(R.id.etMessage);
In your case your code is setting text to EditText before it's initialized.
Best practice is send data via Bundle to Fragment and set Text after EditText is initialized.
Check this answer
Sample Code:
In EditTodoActivity
message = getIntent().getStringExtra(IntentConstants.INTENT_MESSAGE_DATA);
if (fragment == null){
editTodoFragment = new EditTodoFragment();
//
Bundle bundle = new Bundle();
bundle.putInt(key, message);
fragment.setArguments(bundle);
fm.beginTransaction()
.add(R.id.contentFrameContainer, editTodoFragment)
.commit();
editTodoPresenter = new EditTodoPresenter(editTodoFragment);
}
In EditTodoFragment onCreate
Bundle bundle = this.getArguments();
if (bundle != null) {
message = bundle.getString(key, defaultValue);
}
In EditTodoFragment onCreateView
etMessage = (EditText) view.findViewById(R.id.etMessage);
etMessage.setText(message);

Probably the error is that you have defined etMessage in other file than edit_todo_fragment. That's why you are not getting a compilation error, since the reference to etMessage exists, but it does not exists in your inflated view so thus you got the NPE.

As I understood from logs you're calling setMessage method from onCreate method of your activity. But the problem is Activity's onCreate is called earlier than Fragment's onCreateView, so your EditText is not initialized at that moment.

first you have to define this EditText belong to witch view
then, after you inflate your view you should do this.
View view = inflater.inflate(R.layout.edit_todo_fragment, container, false);
etMessage = view.findViewById(R.id.etMessage);
etMessage.setText("your message...")
if you call set text before it, you see this error
or
this view (etMessage) is not in this layout (edit_todo_fragment)

Related

EditTextPreference crashes on requestFocus()

I am migrating from a PreferenceActivity to a PreferenceFragment (v14) and when I try to tap on my EditTextPreference the app crashes.
The code worked with the PreferenceActivity, which is why I don't really understand why it throws a NullPointerException.
Here is the important part of the code:
private Preference websitePref;
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.preferences, rootKey);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
view.setBackgroundColor(getResources().getColor(android.R.color.white));
websitePref = findPreference(getString(R.string.preference_key));
websitePref.setIconSpaceReserved(false);
final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
final String savedWebsite = sharedPrefs.getString(websitePref.getKey(), "");
websitePref.setSummary(savedWebsite);
...
I tried changing the Preference to EditTextPreference and casting it, but I still get the same error:
10-05 13:55:36.694 22397-22397/de.test.browserelement E/AndroidRuntime: FATAL EXCEPTION: main
Process: de.test.browserelement, PID: 22397
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.widget.EditText.requestFocus()' on a null object reference
at android.support.v14.preference.EditTextPreferenceDialogFragment.onBindDialogView(EditTextPreferenceDialogFragment.java:66)
at android.support.v14.preference.PreferenceDialogFragment.onCreateDialog(PreferenceDialogFragment.java:149)
at android.app.DialogFragment.onGetLayoutInflater(DialogFragment.java:410)
at android.app.Fragment.performGetLayoutInflater(Fragment.java:1435)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1279)
at android.app.FragmentManagerImpl.addAddedFragments(FragmentManager.java:2422)
at android.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2201)
at android.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2155)
at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2056)
at android.app.FragmentManagerImpl$1.run(FragmentManager.java:719)
at android.os.Handler.handleCallback(Handler.java:808)
at android.os.Handler.dispatchMessage(Handler.java:101)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
Here is my EditTextPreference in my preferences.xml:
<EditTextPreference
android:defaultValue="#string/preference_default"
android:key="#string/preference_key"
android:selectAllOnFocus="true"
android:singleLine="true"
android:title="#string/preference_title"
android:dependency="#string/sperr_key"
android:inputType="textVisiblePassword" />
I had the same problem. For some reason it does not set the dialog layout by default.
Try casting it to EditTextPreference and add this line of code:
websitePref.setDialogLayoutResource(R.layout.preference_dialog_edittext);

Fragment's view placed inside a FrameLayout throws a NullPointerException

I'm trying to use a FrameLayout on one of my activities. I want this FrameLayout to be a placeholder in an activity and I want to add/replace/remove fragments inside it.
I have a simple cafe app used for studying android. For simplicity I will post the code for the Cake and Breads category.
Problem: NullPointerException. I don't know the reason WHY my fragment's view is null. I'm guessing maybe the fragment lifecycle didn't run so the view was not inflated thus accessing the view throws a nullpointer? Please help me understand WHY a nullpointer is thrown.
Flow of the App
User selects a specific cake or bread in a ListFragment > CakeAndBreadActivity is called > Display Cake or Bread specific detail
I'm looking for: the explanation and reason behind the NullPointerException in the view and How can I display the Cakes and Bread details into the fragment when using FrameLayout.
NullPointerException
--------- beginning of crash
10-25 01:41:21.550 2374-2374/com.cafe E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cafe, PID: 2374
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cafe/com.cafe.CakeAndBreadActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference
at com.cafe.CakeAndBreadDetailFragment.displayCakeAndBreadDetails(CakeAndBreadDetailFragment.java:97)
at com.cafe.CakeAndBreadActivity.displayCakeAndBreadDetails(CakeAndBreadActivity.java:30)
at com.cafe.CakeAndBreadActivity.onCreate(CakeAndBreadActivity.java:19)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
at android.app.ActivityThread.-wrap11(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
CakeAndBreadActivity
public class CakeAndBreadActivity extends Activity implements CakeAndBreadDetailFragment.onCakeAndBreadDetailFragmentListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cake_and_bread);
displayCakeAndBreadDetails();
}
public void displayCakeAndBreadDetails(){
Intent cakeAndBreadIntent = getIntent();
int cakeAndBreadId = Integer.valueOf(cakeAndBreadIntent.getIntExtra("cakeAndBreadNumber", 0));
CakeAndBreadDetailFragment cakeAndBreadDetail = new CakeAndBreadDetailFragment();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
cakeAndBreadDetail.displayCakeAndBreadDetails(cakeAndBreadId);
fragmentTransaction.replace(R.id.cake_and_bread_detail_frame_layout_id, cakeAndBreadDetail);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
#Override
public void onCakeAndBreadDetail(int id) {
}
}
activity_cake_and_bread.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.cafe.CakeAndBreadActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/cake_and_bread_detail_frame_layout_id"/>
</LinearLayout>
CakeAndBreadDetailFragment
public class CakeAndBreadDetailFragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private onCakeAndBreadDetailFragmentListener mListener;
public CakeAndBreadDetailFragment() {
}
public static CakeAndBreadDetailFragment newInstance(String param1, String param2) {
CakeAndBreadDetailFragment fragment = new CakeAndBreadDetailFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_cake_and_bread_detail, container, false);
}
public void onButtonPressed(int id) {
if (mListener != null) {
mListener.onCakeAndBreadDetail(id);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof onCakeAndBreadDetailFragmentListener) {
mListener = (onCakeAndBreadDetailFragmentListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement onCakeAndBreadDetailFragmentListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface onCakeAndBreadDetailFragmentListener {
// TODO: Update argument type and name
void onCakeAndBreadDetail(int id);
}
public void displayCakeAndBreadDetails(int id){
CakeAndBread cakeAndBread = (CakeAndBread)CakeAndBread.getCakeAndBreadList().get(id);
View cakeAndBreadView = getView();
TextView cakeAndBreadTextView = (TextView)cakeAndBreadView.findViewById(R.id.cake_and_bread_detail_fragment_id);
cakeAndBreadTextView.setText(cakeAndBread.getCakeAndBreadName() + " " + cakeAndBread.getCakeAndBreadNutritionFacts());
}
}
fragment_cake_and_bread_detail.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.cafe.CakeAndBreadDetailFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/cake_and_bread_detail_fragment_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
EDIT: as suggested, the fragment was not completely loaded when I'm trying to access the view, thus the nullpointerexception is thrown. Now my problem is the framelayout or the fragment doesn't show the textview that I placed in the fragment, how do I solve this? I'm passing cake and bread id and then setting the text in the setText(...) method of the TextView.
cakeAndBreadDetail.displayCakeAndBreadDetails(cakeAndBreadId);
fragmentTransaction.replace(R.id.cake_and_bread_detail_frame_layout_id, cakeAndBreadDetail);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
You are calling displayCakeAndBreadDetails(..) which calls displayCakeAndBreadDetails(..) which calls getView().
At that point you haven't inserted the fragment yet (happens after fragmentTransaction.commit();) so there is no view associated with the fragment. Hence getView() returns null.
#Kiskae is correct. You're calling cakeAndBreadDetail.displayCakeAndBreadDetails(cakeAndBreadId), when the fragment isn't ready which will result in a NullPointerException. Try:
public class CakeAndBreadActivity extends Activity implements CakeAndBreadDetailFragment.onCakeAndBreadDetailFragmentListener {
public void displayCakeAndBreadDetails(){
Intent cakeAndBreadIntent = getIntent();
int cakeAndBreadId = Integer.valueOf(cakeAndBreadIntent.getIntExtra("cakeAndBreadNumber", 0));
CakeAndBreadDetailFragment cakeAndBreadDetail = CakeAndBreadDetailFragment.newInstance(cakeAndBreadId);
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.cake_and_bread_detail_frame_layout_id, cakeAndBreadDetail);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
public class CakeAndBreadDetailFragment extends Fragment {
private static final String ARG_CAKE_AND_BREAD_ID = "ARG_CAKE_AND_BREAD_ID";
public CakeAndBreadDetailFragment() {
}
public static CakeAndBreadDetailFragment newInstance(int cakeAndBreadId) {
CakeAndBreadDetailFragment fragment = new CakeAndBreadDetailFragment();
Bundle args = new Bundle();
args.putInt(ARG_CAKE_AND_BREAD_ID, cakeAndBreadId);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_cake_and_bread_detail, container, false);
if (getArguments != null) {
int cakeAndBreadId = getArguments.getInt(ARG_CAKE_AND_BREAD_ID, -1);
if (cakeAndBreadId != -1) {
displayCakeAndBreadDetails(cakeAndBreadId);
}
}
return view;
}
public void displayCakeAndBreadDetails(int id){
...
}
}

(ImageView)findViewById() always returns null

I got a problem where findViewById() always returns null for the ImageView in my Dialog:
private void startDetailView(int num)throws NullPointerException{
Dialog detailed = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
detailed.setContentView(R.layout.activity_detail_view);
TextView text = (TextView)detailed.findViewById(R.id.detailedTextView);
ImageView picture = (ImageView)findViewById(R.id.detailedImageView);
detailed.show();
/*picture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
final Dialog dial = new Dialog(ScrollActivity.this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
dial.setContentView(R.layout.picture_view);
FrameLayout cont = (FrameLayout)findViewById(R.id.container);
cont.setBackground(getResources().getDrawable(R.drawable.vine));
dial.show();
cont.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
dial.dismiss();
}
});
}
});*/
}
XML:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/detailedImageView"
android:layout_below="#+id/detailedTextView"
android:layout_centerHorizontal="true"
android:layout_marginTop="134dp" />
The Error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.FrameLayout.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at at.tryouts.mcfuckinvineapp.wein.ScrollActivity$1.onClick(ScrollActivity.java:78)
at android.view.View.performClick(View.java:5280)
at android.view.View$PerformClick.run(View.java:21239)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
This also occurs in the FrameLayout in the second Dialog. Interstingly only these two are affected, I can add any other View without any problem.
I hope you can help me, I can't imagine what's wrong with it.
It may have mistaken Activity view from Detailed view. I bet your ImageView is under Detailed View since it was "layout_below:detailedTextView". Try Changing it to
ImageView picture = (ImageView) detailed.findViewById(R.id.detailedImageView);

How to call a method within a programmatically generated fragment from the parent activity?

EDIT 4 Alright, so I've changed my example code to exactly what was suggested, with a null check.
now in the public class MainActivity extends AppCompatActivity I've got
private templateFragment1 fragTest;
and then in onCreate I've got
final FragmentManager fragMan = getFragmentManager();
fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
if(fragTest != null) {
String editTestText = fragTest.editTextGetter();
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
}
});
And in templateFragment1 I've got
privateEditText text;
which I've binded in onCreateView like this
text = (EditText) getActivity().findViewById(R.id.editTextTest);
then I have the method underneath onCreateView
public String editTextGetter(){
String value1 = text.getText().toString();
return value1;
}
And now what happens..is nothing. I hit the save button and there's no Toast, no error message. So I guess this means it's returning null?
EDIT 3 Here's a couple videos demonstrating the bug.
https://www.youtube.com/watch?v=w60Vljd2R4M&feature=youtu.be
https://www.youtube.com/watch?v=xqpVGBAHw0w&feature=youtu.be
I understand that there are several questions similar to this already, but none seem to address my specific issue here.
Inside my main activity I have a button that adds instances of fragments. Each time it does it also assigns them a tag of "1", "2", etc. Just to see if it's possible, I'm only trying to call a method from the first one.
In my main activity I have:
// initializing button that will call the fragment's method
Button onSave = (Button) findViewById(R.id.saveButton);
FragmentManager fragMan = getFragmentManager();
// calling my first created fragment
final templateFragment1 fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
// my button that should call the frag's method and then display it as a toast
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// here I'm assigning the fragment's method to a string
String editTestText = fragTest.editTextGetter();
// display as toast
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
});
In my fragment:
public String editTextGetter(){
EditText text = (EditText) getActivity().findViewById(R.id.editTextTest);
String value1 = text.getText().toString();
return value1;
}
editTextGetter() is below the onCreateView method if that matters.
Now what happens is just an app crash upon clicking the main activity's button.
EDIT: Here's my commit code as requested:
addDay.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
++fragIdCount;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
}
});
As you can see, I'm incrementing a number from 0 (fragIdCount) and then converting it to a string. I then assign that as the tag of the fragment. So I'm trying to call my fragments with this assigned tag.
EDIT 2: OK guys, here's code that can copy+pasted into a new project. It replicates my issues, and I'd really appreciate if yall could take a look at it!
MainActivity.java
public class MainActivity extends AppCompatActivity {
int fragIdCount = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addDay = (Button) findViewById(R.id.addDay);
Button removeDay = (Button) findViewById(R.id.removeDay);
// Here I'm making it so I have an instance of the fragment displayed on create
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
// My button that adds fragment. Obviously this can quickly generate a bunch of fragment instances
// I try to make that manageable by incrementing a fragment count to use as tags
addDay.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
++fragIdCount;
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
templateFragment1 frag2 = new templateFragment1();
fragmentTransaction.add(R.id.templateFragmentLayout, frag2, fragString);
fragmentTransaction.commit();
fragmentManager.executePendingTransactions();
}
});
// remove button. same concept as the add button
removeDay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
String fragString = Integer.toString(fragIdCount);
//Fragment f = getFragmentManager().findFragmentByTag(fragString);
if(fragIdCount != 0){
fragmentTransaction.remove(fragmentManager.findFragmentByTag(fragString)).commit();
--fragIdCount;
}
}
});
// initialize Save button (which SHOULD get the value of an editText from whichever
// fragment I specify)
Button onSave = (Button) findViewById(R.id.saveButton);
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// Eventually I'll want to make this a for loop to perform this operation on all fragments created.
FragmentManager fragMan = getFragmentManager();
// this should get the fragment "1"
templateFragment1 fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
// and this should run the method "editTextGetter()" inside of the previously specified fragment
String editTestText = fragTest.editTextGetter();
// just a quick way to show if I got the correct value, for debugging
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
});
}
}
activity_main.xml
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.liftrpoc.scheduler1.pushpulldetails"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/templateFragmentLayout"
android:orientation="vertical">
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/addDay"
android:text="Add Day"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/removeDay"
android:text="Remove Day"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/saveButton"
android:text="Save"
/>
</LinearLayout>
</ScrollView>
templateFragment1.java
public class templateFragment1 extends Fragment {
public templateFragment1() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
LinearLayout view = (LinearLayout) inflater.inflate(R.layout.fragment_template_fragment1, container, false);
// a good bit of extra code that adds it's own instanced fragments, just like in the main activity.
// this shouldn't have anything to do with what we're trying to do though. It doesn't touch anything else.
return view;
}
// here's the editText method I'm trying to access from my main activity.
public String editTextGetter(){
EditText text = (EditText) getActivity().findViewById(R.id.editTextTest);
String value1 = text.getText().toString();
return value1;
}
}
fragment_template_fragment1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E3E3E3"
android:orientation="vertical"
android:id="#+id/ParentLinearLayout1"
>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/editTextTest"
/>
</LinearLay
Use an ArrayList and store each fragment you make in it.
then when you want to call an specific function in your fragment or get a view just get your desired fragment from the ArrayList and after that do your job.
Some areas of improvement to your code:
In your main activity, it's easier to just make fragTest a class property.
private templateFragment1 fragTest;
/** I believe these exists in your onCreate()? **/
// initializing button that will call the fragment's method
Button onSave = (Button) findViewById(R.id.saveButton);
FragmentManager fragMan = getFragmentManager();
// calling my first created fragment
fragTest = (templateFragment1) fragMan.findFragmentByTag("1");
if(fragTest == null) {
// Create fragTest
}
// my button that should call the frag's method and then display it as a toast
onSave.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
// Wrapping this with a null pointer check may be unnecessary
// but callbacks can be ... funny.
if(fragTest != null {
// here I'm assigning the fragment's method to a string
String editTestText = fragTest.editTextGetter();
// display as toast
Toast.makeText(getApplicationContext(), editTestText, Toast.LENGTH_SHORT).show();
}
}
});
/** End of onCreate **/
In your fragment, again, make text a class property and bind to it's view in onCreateView.
private EditText text;
// TODO In onCreateView, bind text to R.id.editTextTest
public String editTextGetter(){
String value1 = text.getText().toString();
return value1;
}
Other considerations
Orientation changes: you may want to add setRetainInstance(true) to the onCreate of you fragments. Full details here.

Error Android Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)'

I have a fragment with button, on click the button should change the theme in my app but when i open the class i simply get this error: This is the logcat
08-14 21:32:45.914 29624-29624/addid E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: appid, PID: 29624
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
at appid.Fragment.GuidaTv.InitView(GuidaTv.java:75)
at appid.Fragment.GuidaTv.onCreateView(GuidaTv.java:41)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1789)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:955)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:740)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
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:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
My Class:
public class GuidaTv extends Fragment implements View.OnClickListener{
private Button FirstThemButton;
private Button SecondThemButton;
private Button ThirdThemButton;
private SharedPreferences sharePrefences;
private SharedPreferences.Editor editor;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.guida_tv,container,false);
SharePreference();
InitView();
FirstThemButton =(Button) v.findViewById(R.id.FirstThem);
SecondThemButton =(Button) v.findViewById(R.id.SecondThem);
SecondThemButton =(Button) v.findViewById(R.id.ThirdThem);
return v;
}
private void SharePreference() {
sharePrefences=this.getActivity().getSharedPreferences("config", Context.MODE_WORLD_READABLE
| Context.MODE_WORLD_WRITEABLE);
editor=sharePrefences.edit();
boolean isThem = sharePrefences.getBoolean("isThem", false);
int Them = sharePrefences.getInt("Them",0);//config不存在时返回0
if(isThem){
if(Them==1){
getActivity().setTheme(R.style.AppTheme2);
}else if(Them==2){
getActivity().setTheme(R.style.AppTheme2);
}else if(Them==3){
getActivity().setTheme(R.style.AppTheme2);
}
}else{//sharePrefences不存在是使用默认主题
getActivity().setTheme(R.style.AppTheme);
}
}
private void InitView() {
FirstThemButton=(Button) getActivity().findViewById(R.id.FirstThem);
SecondThemButton=(Button) getActivity().findViewById(R.id.SecondThem);
ThirdThemButton=(Button) getActivity().findViewById(R.id.ThirdThem);
FirstThemButton.setOnClickListener(this);
SecondThemButton.setOnClickListener(this);
ThirdThemButton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.FirstThem:
editor.putBoolean("isThem", true);
editor.putInt("Them", 1);
editor.commit();
break;
case R.id.SecondThem:
editor.putBoolean("isThem", true);
editor.putInt("Them",2);
editor.commit();
break;
case R.id.ThirdThem:
editor.putBoolean("isThem", true);
editor.putInt("Them", 3);
editor.commit();
break;
default:
break;
}
}
}
my xml file:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#E5E5E5"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/FirstThem"
android:layout_width="10dp"
android:layout_height="10dp"
android:text="样式一"
/>
<Button
android:id="#+id/SecondThem"
android:layout_width="10dp"
android:layout_height="10dp"
android:text="样式二"
/>
<Button
android:id="#+id/ThirdThem"
android:layout_width="10dp"
android:layout_height="10dp"
android:text="样式三"
/>
Please help me to resolve the problem.
Where is your button located? In the activity or the fragments layout? Looks like you are trying to get it twice. Once from the activity inside InitView(); and then again inside onCreateView();
There lies your problem. If your XML layout is inflated from the activity use getActivity().findViewById(R.id.FirstThem);
If its inside the fragment layout, then use the view.findViewById(R.id.FirstThem);
Code Example:
public class GuidaTv extends Fragment implements View.OnClickListener{
private Button FirstThemButton;
private Button SecondThemButton;
private Button ThirdThemButton;
private SharedPreferences sharePrefences;
private SharedPreferences.Editor editor;
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view =inflater.inflate(R.layout.guida_tv,container,false);
SharePreference();
FirstThemButton =(Button) view.findViewById(R.id.FirstThem);
SecondThemButton =(Button) view.findViewById(R.id.SecondThem);
ThirdThemButton =(Button) view.findViewById(R.id.ThirdThem);
^^^ This is the culprit! Change the name!
InitView();
return view;
}
private void SharePreference() {
sharePrefences=this.getActivity().getSharedPreferences("config", Context.MODE_WORLD_READABLE
| Context.MODE_WORLD_WRITEABLE);
editor=sharePrefences.edit();
boolean isThem = sharePrefences.getBoolean("isThem", false);
int Them = sharePrefences.getInt("Them",0);//config不存在时返回0
if(isThem){
if(Them==1){
getActivity().setTheme(R.style.AppTheme2);
}else if(Them==2){
getActivity().setTheme(R.style.AppTheme2);
}else if(Them==3){
getActivity().setTheme(R.style.AppTheme2);
}
}else{//sharePrefences不存在是使用默认主题
getActivity().setTheme(R.style.AppTheme);
}
}
private void InitView() {
FirstThemButton.setOnClickListener(this);
SecondThemButton.setOnClickListener(this);
ThirdThemButton.setOnClickListener(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.FirstThem:
editor.putBoolean("isThem", true);
editor.putInt("Them", 1);
editor.commit();
break;
case R.id.SecondThem:
editor.putBoolean("isThem", true);
editor.putInt("Them",2);
editor.commit();
break;
case R.id.ThirdThem:
editor.putBoolean("isThem", true);
editor.putInt("Them", 3);
editor.commit();
break;
default:
break;
}
}
Try this.
create one onViewCreated view and place the setOnClickListener inside it.
example:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
buttonName.setOnClickListener {
Toast.makeText(activity,"Success.", Toast.LENGTH_SHORT).show()
}
}

Categories