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

问题描述

我的主要活动有以下代码:

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");
        }
    }

我正在一个Fragment上调用函数InserePessoa。片段的代码是:

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,"Inserção feita com sucesso",null).show();
                //NavHostFragment.findNavController(FirstFragment.this)
                //        .navigate(R.id.action_FirstFragment_to_SecondFragment);

            }
        });
    }
}

当我从Fragment调用函数inserePessoa时,应用程序被最小化,并且代码在日志消息“ Log.d(” Insere“,” Func inserePessoa iniciada“);”上停止运行;“其他消息未出现在logcat上,因为应用程序在该部分停止。

我认为这是因为在从Fragment调用inserePessoa函数时缺少某些东西。

为什么会这样?我该如何运作?

**我上了logcat:

2020-10-26 17:15:54.885 27220-27220 /? D / Insere:Sistema entrando na 主要活动2020-10-26 17:15:54.886 27220-27220 /? D / Insere:克里斯多·奥 达多斯银行2020-10-26 17:16:08.767 27220-27220 /? D / Insere:功能 inserePessoa iniciada 2020-10-26 17:17:36.753 28648-28648 /? D / Insere: Sistema entrando na主要活动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

我得到的错误是:

2020-10-26 21:11:25.167 27342-27342 / br.com.pim E / Android运行时:致命 例外:主要 流程:br.com.pim,PID:27342 java.lang.NullPointerException:尝试在null上调用虚拟方法'android.text.Editable android.widget.EditText.getText()' 对象参考 在br.com.pim.MainActivity.inserePessoa(MainActivity.java:56) 在br.com.pim.FirstFragment $ 1.onClick(FirstFragment.java:37) 在android.view.View.performClick(View.java:7339) 在android.widget.TextView.performClick(TextView.java:14222) 在com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:967) 在android.view.View.performClickInternal(View.java:7305) 在android.view.View.access $ 3200(View.java:846) 在android.view.View $ PerformClick.run(View.java:27787) 在android.os.Handler.handleCallback(Handler.java:873) 在android.os.Handler.dispatchMessage(Handler.java:99) 在android.os.Looper.loop(Looper.java:214) 在android.app.ActivityThread.main(ActivityThread.java:7091) 在java.lang.reflect.Method.invoke(本机方法) 在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:494) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

textview是在以下片段(XML代码如下)上定义的:

<?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>

解决方法

您应该访问定义视图的位置,因此您应该从片段而不是活动中访问CPF和Nome。移动变量

 EditText Nome,CPF;
 CadastroBD helper;

插入片段,并将其绑定到onViewCreated

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

现在您可以从片段中访问视图。

回到您的问题。有几种技术可以访问该活动。其中之一当然是您的操作方式,但这并不是可取的,因为它与活动紧密耦合(您明确地转换为MainActivity)。这有点违背了使用片段的目的。除了我将要解释的那一种之外,还有一种“反应”技术,其中Activity观察状态,并且当该片段设置新状态时,Activ对它做出反应。

我将解释的是通过接口或回调。您在活动内部定义了一个界面,例如

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() ) ;
                    }
                  
                }
            });
        }
,

用于在片段上使用活动方法,您的活动在该片段之前最常实现。 我在您的代码中看到的是您在另一个不在主要活动中的地方调用您的片段 因此您的活动未实现且onCreate()方法未调用,因此当您使用edittext时,它会产生nullpointerexception。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...