java.lang.RuntimeException: Unable to start activity, java.lang.NullPointerException in Android Studio

2

Making a code to simply show Hello, world in a TextView named st, which is referred to by the variable stat, the error comes out:

java.lang.RuntimeException: Unable to start activity ComponentInfo      {com.aapps.vyber.clicker/com.aapps.vyber.app.MainActivity}: java.lang.NullPointerException:

Referring to the last line of instructions onCreate (), in which I try to place the text by means of setText ().

MainActivity.xml - > You only have the options bar below

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fragment_container"
    android:layout_above="@+id/navigation"/>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginEnd="0dp"
    android:layout_marginStart="0dp"
    android:background="?android:attr/windowBackground"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:menu="@menu/navigation"
    android:layout_alignParentBottom="true"/>

</RelativeLayout>

MainActivity.java - > With this class, I want to change the text of a TextView of Fragment.xml

package com.aapps.vyber.app;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;

import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    public TextView stat;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        stat = (TextView) findViewById(R.id.st);
        stat.setText("Hola, mundo");
    }

}

I also defined a new method by which type text is put,

void do_it(){
    stat.setText("Hola, mundo");
}

To invoke it from onCreate () instead of putting the setText () directly, but it still does not work.

Here is the XML of the Fragment. The MainActivity is completely empty, so I do not see its inclusion important

Fragment.xml - > It has the TextView that I want to reference

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

<TextView
    android:id="@+id/st"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="403dp"
    android:text="Quiero cambiarme"
    android:textAlignment="center"
    android:textSize="18sp" />

</RelativeLayout>

FragmentActivity.java - > You only have the code to change according to the toolbar

package com.aapps.vyber.app;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FragmentActivity extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.Fragment, container, false);
    }
}

Any big mistake out there? Thank you for your dedication and help in advance.

NOTE

st exists and is in a layout, only not in the MainActivity. It is in a fragment. If that is the reason for the problem, of course, I'd love to be notified of how to fix it by keeping the TextView in the snippet. However, the IDE does not point me to the text as impossible to achieve. Also, all the variables and values that I use are defined and I have tried not to use import methods that can return null values

    
asked by Vyber90 30.07.2018 в 12:26
source

1 answer

4

If you try to perform a reference search for an id not existing in your layout, instantiate it and invoke some method in the instance, it will always cause NullPointerException .

Solution to your problem

First of all, remove the code from your Activity that belongs to Fragment :

stat = (TextView) findViewById(R.id.st);
stat.setText("Hola, mundo");

and move it to onCreateView of your Fragment :

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    // Referencia del Layout, esto es mas o menos lo mismo que hacer setContentView en un Activity
    View view = inflater.inflate(R.layout.Fragment, container, false);
    stat = (TextView) view.findViewById(R.id.st); // Aqui no devuelve null, porque st esta en el layout Fragment.axml que carga el inflate
    stat.setText("Hola, mundo");
    return view;
}

Notice that the root where you are going to do findViewById must refer to the loaded layout. To be able to reference the views in Fragment , you must do it in your class and with the layout of the same, in this case your reference stored in the local view variable of type View .

Example:

TextView tv = (TextView) view.findViewById(R.id.***)...
Button btn = (Button) view.findViewById(R.id.***)...

etc ...

How to communicate actions between Activiy-Fragment and vice versa?

Let's say that now you want to modify some value of your Fragment from the Activity. To do this, it must be active in the Fragment backstack, and according to the official documentation , communication between the activity and the Fragment should be done as follows:

From Fragment to Activity :

Let's say you have a Fragment called MyFragment . You create a private variable that will be the listener to invoke:

private OnExampleListener listener;

You must create a communication interface between the Fragment and the Activity. First declares an interface that belongs to the space of the Fragment, this to be able to identify it as such.

// La actividad que contiene al Fragment debe implementar esta interfaz
public interface OnExampleListener {
    public void onExample(); // Aqui creas uno o mas metodos que implementaras
}

Once this is done, you must subscribe the listener, the best way is while the fragment is attached to the activity, that is, when it was created and it is in the stack (onAttach):

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        // Si la instancia de tu Actividad, implementa la interfaz, esta sera a quien se va a invocar en la interacción
        try {
            listener = (OnExampleListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " esta actividad no implementa OnExampleListener");
        }
    }

Once this is done, in your Activity, you implement the Fragment interface:

public class MainActivity extends Activity
        implements MyFragment.OnExampleListener{
    ...

    // Este método pertenece a la interfaz y se llamara al ser invocado
    public void onExample() {
         // Aqui haces lo que desees al ser invocado el metodo de la interfaz
    }
}

and already to invoke the action in any part of the Fragment either in an onClick or anywhere, you call it like this:

if(listener != null)
   listener.onExample();

From Activity to Fragment :

If it's an action like onBackPressed you can do the same trick of the interfaces but in an inverse way, however, if you only want to invoke a method from the Activity to the Fragment, you must do the following:

MyFragment mFragment = (MyFragment)
                getSupportFragmentManager().findFragmentById(R.id./*id del contenedor del Fragment (FrameLayout) en tu activity*/);

        if (mFragment != null) {
            // Si el fragment esta en el contenedor, aqui invocas su accion.

            // llama un metodo del Fragment
            mFragment.exampleMethod("Hola mundo desde el Activity");
        }

and already in your Fragment, you will decide what to do in your method, when invoked:

public void exampleMethod(String text){
    // Aqui haces lo que desees, en tu ejemplo, hacer setText desde el Activity
    if(stat != null && text != null)
       stat.setText(text);
}
    
answered by 30.07.2018 / 16:02
source