Android/Java应用程序 – 如何正确从片段调用活动函数?

huangapple go评论73阅读模式
英文:

Android/Java application - How to call a activity function from a fragment properly?

问题

public class MainActivity extends AppCompatActivity {
    static EditText Nome, CPF;
    static CadastroBD helper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        Log.d("Insere", "Sistema entrando na Main Activity");

        Nome= (EditText) findViewById(R.id.Nome_In);
        CPF= (EditText) findViewById(R.id.CPF_In);

        helper = new CadastroBD(this);

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Selecione a aplicação com que deseja compartilhar os dados", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

    public void inserePessoa(View view) {
        Log.d("Insere", "Func inserePessoa iniciada");
        String t1 = Nome.getText().toString();
        String t2 = CPF.getText().toString();
        Log.d("Insere", "Func inserePessoa - variáveis iniciadas");

        if(t1.isEmpty() || t2.isEmpty()) {
            Log.d("Insere", "Func inserePessoa - Campo em branco");
            Message.message(getApplicationContext(), "Entre com o Nome e o CPF");
        } else {
            Log.d("Insere", "Func InserePessoa - chamando insertDataPessoa");
            long id = helper.insertDataPessoa(t1,t2);
            if(id <= 0) {
                Message.message(getApplicationContext(), "Insertion Unsuccessful");
                Nome.setText("");
                CPF.setText("");
            } else {
                Message.message(getApplicationContext(), "Insertion Successful");
                Nome.setText("");
                CPF.setText("");
            }
            Log.d("Insere", "Func InserePessoa - Finalizando");
        }
    }
}
public class FirstFragment extends Fragment {

    @Override
    public View onCreateView(
            LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState
    ) {
        return inflater.inflate(R.layout.fragment_first, container, false);
    }

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ((MainActivity)getActivity()).inserePessoa(view);

                Snackbar.make(view, "Inserção feita com sucesso", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }
}

XML code for fragment_first:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FirstFragment">

    <TextView
        android:id="@+id/textview_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="72dp"
        android:text="Cadastre o nome e o CPF"
        android:textSize="22dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.198"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="44dp"
        android:text="Cadastrar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent" />

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:layout_editor_absoluteX="122dp"
        tools:layout_editor_absoluteY="208dp"
        tools:ignore="MissingConstraints">

    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/Nome_In"
        android:layout_width="325dp"
        android:layout_height="52dp"
        android:layout_marginTop="68dp"
        android:hint="Nome"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/textview_first"
        app:layout_constraintTop_toBottomOf="@+id/textview_first" />

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:layout_editor_absoluteX="65dp"
        tools:layout_editor_absoluteY="277dp"
        tools:ignore="MissingConstraints">

    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/CPF_In"
        android:layout_width="325dp"
        android:layout_height="52dp"
        android:layout_marginTop="68dp"
        android:hint="CPF"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="@+id/Nome_In"
        app:layout_constraintTop_toBottomOf="@+id/Nome_In" />
</androidx.constraintlayout.widget.ConstraintLayout>

Note: The provided code snippets have been translated from the original text to the best of my ability. Please make sure to verify and test the code in your project to ensure its correctness.

英文:

I have this code for my Main Activity:

public class MainActivity extends AppCompatActivity {
static EditText Nome, CPF;
static CadastroBD helper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Log.d(&quot;Insere&quot;, &quot;Sistema entrando na Main Activity&quot;);
Nome= (EditText) findViewById(R.id.Nome_In);
CPF= (EditText) findViewById(R.id.CPF_In);
helper = new CadastroBD(this);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, &quot;Selecione a aplica&#231;&#227;o com que deseja compartilhar os dados&quot;, Snackbar.LENGTH_LONG)
.setAction(&quot;Action&quot;, null).show();
}
});
}
public void inserePessoa(View view)
{
Log.d(&quot;Insere&quot;, &quot;Func inserePessoa iniciada&quot;);
String t1 = Nome.getText().toString();
String t2 = CPF.getText().toString();
Log.d(&quot;Insere&quot;, &quot;Func inserePessoa - vari&#225;veis iniciadas&quot;);
if(t1.isEmpty() || t2.isEmpty())
{
Log.d(&quot;Insere&quot;, &quot;Func inserePessoa - Campo em branco&quot;);
Message.message(getApplicationContext(),&quot;Entre com o Nome e o CPF&quot;);
}
else
{
Log.d(&quot;Insere&quot;, &quot;Func InserePessoa - chamando insertDataPessoa&quot;);
long id = helper.insertDataPessoa(t1,t2);
if(id&lt;=0)
{
Message.message(getApplicationContext(),&quot;Insertion Unsuccessful&quot;);
Nome.setText(&quot;&quot;);
CPF.setText(&quot;&quot;);
} else
{
Message.message(getApplicationContext(),&quot;Insertion Successful&quot;);
Nome.setText(&quot;&quot;);
CPF.setText(&quot;&quot;);
}
Log.d(&quot;Insere&quot;, &quot;Func InserePessoa - Finalizando&quot;);
}
}

I am calling the function InserePessoa on a Fragment. The code of the Fragment is:

public class FirstFragment extends Fragment {
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_first, container, false);
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)getActivity()).inserePessoa(view);
Snackbar.make(view, &quot;Inser&#231;&#227;o feita com sucesso&quot;, Snackbar.LENGTH_LONG)
.setAction(&quot;Action&quot;, null).show();
//NavHostFragment.findNavController(FirstFragment.this)
//        .navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
}

When I call the function inserePessoa from the Fragment, the application is minimized and the code stops on the log message "Log.d("Insere", "Func inserePessoa iniciada");" The other messages does not appear on logcat because the application stops on that part.

I think it happens because I am missing something when calling the inserePessoa function from the Fragment.

Why is it happening? How can I make it work?

**I get on logcat:

> 2020-10-26 17:15:54.885 27220-27220/? D/Insere: Sistema entrando na
> Main Activity 2020-10-26 17:15:54.886 27220-27220/? D/Insere: Criado o
> Banco de Dados 2020-10-26 17:16:08.767 27220-27220/? D/Insere: Func
> inserePessoa iniciada 2020-10-26 17:17:36.753 28648-28648/? D/Insere:
> Sistema entrando na Main Activity 2020-10-26 17:17:36.754
> 28648-28648/? D/Insere: Criado o Banco de Dados 2020-10-26
> 17:17:48.000 28648-28648/? D/Insere: Func inserePessoa iniciada

The error that I am getting is:

> 2020-10-26 21:11:25.167 27342-27342/br.com.pim E/AndroidRuntime: FATAL
> EXCEPTION: main
> Process: br.com.pim, PID: 27342
> java.lang.NullPointerException: Attempt to invoke virtual method 'android.text.Editable android.widget.EditText.getText()' on a null
> object reference
> at br.com.pim.MainActivity.inserePessoa(MainActivity.java:56)
> at br.com.pim.FirstFragment$1.onClick(FirstFragment.java:37)
> at android.view.View.performClick(View.java:7339)
> at android.widget.TextView.performClick(TextView.java:14222)
> at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967)
> at android.view.View.performClickInternal(View.java:7305)
> at android.view.View.access$3200(View.java:846)
> at android.view.View$PerformClick.run(View.java:27787)
> at android.os.Handler.handleCallback(Handler.java:873)
> at android.os.Handler.dispatchMessage(Handler.java:99)
> at android.os.Looper.loop(Looper.java:214)
> at android.app.ActivityThread.main(ActivityThread.java:7091)
> at java.lang.reflect.Method.invoke(Native Method)
> at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

The textview is defined on the fragment, XML code bellow:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
xmlns:tools=&quot;http://schemas.android.com/tools&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;match_parent&quot;
tools:context=&quot;.FirstFragment&quot;&gt;
&lt;TextView
android:id=&quot;@+id/textview_first&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_marginTop=&quot;72dp&quot;
android:text=&quot;Cadastre o nome e o CPF&quot;
android:textSize=&quot;22dp&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.198&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;
&lt;Button
android:id=&quot;@+id/button_first&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_marginBottom=&quot;44dp&quot;
android:text=&quot;Cadastrar&quot;
app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.498&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot; /&gt;
&lt;com.google.android.material.textfield.TextInputLayout
android:id=&quot;@+id/textInputLayout&quot;
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;wrap_content&quot;
tools:layout_editor_absoluteX=&quot;122dp&quot;
tools:layout_editor_absoluteY=&quot;208dp&quot;
tools:ignore=&quot;MissingConstraints&quot;&gt;
&lt;/com.google.android.material.textfield.TextInputLayout&gt;
&lt;com.google.android.material.textfield.TextInputEditText
android:id=&quot;@+id/Nome_In&quot;
android:layout_width=&quot;325dp&quot;
android:layout_height=&quot;52dp&quot;
android:layout_marginTop=&quot;68dp&quot;
android:hint=&quot;Nome&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.0&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/textview_first&quot;
app:layout_constraintTop_toBottomOf=&quot;@+id/textview_first&quot; /&gt;
&lt;com.google.android.material.textfield.TextInputLayout
android:layout_width=&quot;match_parent&quot;
android:layout_height=&quot;wrap_content&quot;
tools:layout_editor_absoluteX=&quot;65dp&quot;
tools:layout_editor_absoluteY=&quot;277dp&quot;
tools:ignore=&quot;MissingConstraints&quot;&gt;
&lt;/com.google.android.material.textfield.TextInputLayout&gt;
&lt;com.google.android.material.textfield.TextInputEditText
android:id=&quot;@+id/CPF_In&quot;
android:layout_width=&quot;325dp&quot;
android:layout_height=&quot;52dp&quot;
android:layout_marginTop=&quot;68dp&quot;
android:hint=&quot;CPF&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.0&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/Nome_In&quot;
app:layout_constraintTop_toBottomOf=&quot;@+id/Nome_In&quot; /&gt;
&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;

答案1

得分: 1

你应该访问定义了这些视图的视图,所以应该从片段中访问CPF和Nome,而不是从活动中访问。将变量

EditText Nome, CPF;
CadastroBD helper;

移到片段中,并在onViewCreated中进行绑定:

Nome = (EditText) view.findViewById(R.id.Nome_In);
CPF = (EditText) view.findViewById(R.id.CPF_In);

现在你可以从片段中访问这些视图。

关于你的问题,有一些技术可以访问活动。其中之一当然是你正在进行的方式,但由于与活动的紧耦合性(你在明确地将其转换为MainActivity),这并不是一个推荐的方式。这在某种程度上破坏了使用片段的目的。除了我将解释的方法外,还有一种“响应式”的技术,其中活动正在观察状态,当片段设置新状态时,活动会做出响应。

我将解释的方法是通过接口或回调实现的。你在活动中定义一个接口,类似于:

public interface FragmentActions {
    void processData(String parameter1, int parameter2);
}

然后让活动实现这个接口:

public class MainActivity extends AppCompatActivity implements FragmentActions {
    ...

    @Override
    void processData(String parameter1, String parameter2) { 
        Log.d("fragmentaction", "Display data");
    }
}

最后一步是从片段中调用这个接口。首先,我们需要检查底层活动是否实现了这个特定的接口,如果是,则调用你想要的函数:

public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    Nome = (EditText) view.findViewById(R.id.Nome_In);
    CPF = (EditText) view.findViewById(R.id.CPF_In);

    view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (getActivity() instanceof FragmentActions) {
                ((FragmentActions) getActivity()).processData(Nome.getText().toString(), CPF.getText().toString());
            }
        }
    });
}
英文:

You should access the views where they are defined, so you should access CPF and Nome from the fragment and not from the activity. Move the variables

 EditText Nome, CPF;
CadastroBD helper;

into the fragment, and bind them inside onViewCreated

 Nome= (EditText) findViewById(R.id.Nome_In);
CPF= (EditText) findViewById(R.id.CPF_In);

Now you can access the views from the fragment.

To come back to your question. There are couple techniques to access the activity. One of them is of course the way you are doing it, but that is not a preferable one because of the tight coupling to the activity (you are explicitly casting to MainActivity).This kinda defeats the purpose of using a fragment. Besides the one I will explain there is also a "reactive" technique where the Activity is observing a state, and when that the fragment sets a new state the activity reacts to it.

The one I will explain is via interfaces or callbacks. You define an interface inside the activity, something like

public interface FragmentActions {
void processData(String parameter1, int parameter2)
}

Then you let the activity implement this interface:

public class MainActivity extends AppCompatActivity implements FragmentActions {
...
@Override
void processData(String parameter1, String parameter2) { 
Log.d(&quot;fragmentaction&quot;, &quot;Display data&quot;)
}

}

And the last step is to call this interface from the fragment. First we need to check whether the underlying activity is implementing this particular interface, and if so, call the function you want:

    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Nome = (EditText) view.findViewById(R.id.Nome_In);
CPF = (EditText) view.findViewById(R.id.CPF_In);
view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (getActivity() instanceof FragmentActions) {
((FragmentActions) getActivity()).processData(Nome.getText().toString(), 
CPF.getText().toString() ) ;
}
}
});
}

答案2

得分: 0

使用片段中的活动方法之前,您的活动必须先实现该片段。根据您的代码,我看到您在另一个位置调用了片段,而不是在主活动中调用。因此,您的活动未实现,并且未调用onCreate()方法,因此当您使用您的编辑框时,会出现空指针异常。

英文:

for using a method of a activity on a fragment your activity most implement before that fragment.
what I see in your code you are calling your fragment in another place not in main activity
so your activity not implemented and onCreate() method not called so when you are using your edittext its produce nullpointerexception.

huangapple
  • 本文由 发表于 2020年10月27日 07:16:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/64546272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定