[英]How can I split MainActivity functionality into an another class for clarity?
我有一个android程序,我希望能够将MainActivity中的功能拆分为多个文件以保持代码井井有条,但是我收到了空对象引用错误。
为了演示该错误,我创建了一个简单的程序,该程序只有一个textView和一个用于更改textView的按钮。 单击按钮时发生错误。 如何解决此问题,以便可以参加帮助课程?
MainActivity.java
package com.example.testapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
private MainActivityHelper mainActivityHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainActivityHelper = new MainActivityHelper();
}
public void buttonPressed(View view) {
mainActivityHelper.changeText();
}
}
MainActivityHelper.java
package com.example.testapp;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivityHelper extends AppCompatActivity {
public MainActivityHelper() {
}
public void changeText() {
TextView textView = findViewById(R.id.helloString);
if(textView.getText().toString() == "Hello World!") {
textView.setText("Goodbye world!");
}
else {
textView.setText("Hello World!");
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
错误信息:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.testapp, PID: 17322
java.lang.IllegalStateException: Could not execute method for android:onClick
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:389)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:384)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference
at android.support.v7.app.AppCompatDelegateImplBase.<init>(AppCompatDelegateImplBase.java:117)
at android.support.v7.app.AppCompatDelegateImplV9.<init>(AppCompatDelegateImplV9.java:149)
at android.support.v7.app.AppCompatDelegateImplV14.<init>(AppCompatDelegateImplV14.java:56)
at android.support.v7.app.AppCompatDelegateImplV23.<init>(AppCompatDelegateImplV23.java:31)
at android.support.v7.app.AppCompatDelegateImplN.<init>(AppCompatDelegateImplN.java:31)
at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:198)
at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:183)
at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:519)
at android.support.v7.app.AppCompatActivity.findViewById(AppCompatActivity.java:190)
at com.example.testapp.MainActivityHelper.changeText(MainActivityHelper.java:14)
at com.example.testapp.MainActivity.buttonPressed(MainActivity.java:19)
at java.lang.reflect.Method.invoke(Native Method)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:384)
at android.view.View.performClick(View.java:6294)
at android.view.View$PerformClick.run(View.java:24770)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
您有一个空指针,因为尚未设置Main活动助手的内容视图。 在另一个对象中使用和活动不是实现目标的正确方法。
如果您想拥有一个助手类,则不必扩展一个Activity或声明一个为Activity的字段。 最好的方法是使用一个视图模型,该视图模型是mvvm模式中常用的后端类。 视图模型允许将逻辑与活动代码分离。
如果要继续下去,只需声明一个普通的Java类,然后将Activity的引用传递给该类的构造函数。 在主活动的onCreate中类似以下内容:
MainActivityHelper =新的MainActivityHelper(this);
之后,您可以在助手中调用您的活动方法(例如,喜欢findviewbyid)。
希望这会给您一些提示/帮助。
干杯。
您不能只是这样破坏活动。 我建议在活动内部使用片段,这样您就可以用特定的代码段隔离每个片段,并只需简单地调用活动即可(此时,活动是粘贴所有片段的简单容器,用作调解员)。
请看一下这个Android Fragments 。
这可能已经过时了,但这是一个很好的切入点 。
您不能将活动分为扩展AppCompatActivity类的两个类,但是可以有一个辅助程序类或“ Utils”类,其中包含一组静态函数,每个静态函数都用于特定目的。 这样,您可以通过最小化活动代码并将部分代码移到帮助程序类中,使活动代码更具可读性。
另外,您可以将ViewModel与LiveData一起使用以分离数据“获取”逻辑和UI逻辑。 您可以在此处了解更多信息: https : //developer.android.com/jetpack/docs/guide
您将获得NPE
,因为您使用的是findViewById
而不附加内容视图。
您可以创建一个单独的类,然后将此方法和所有其他方法放入其中:
public final class Constants {
public static final String HELLO_WORLD = "Hello World!";
public static final String GOODBYE_WORLD = "Goodbye world!";
}
public class Methods {
public static void changeText(TextView textView) {
if(textView.getText().toString() == Constants.HELLO_WORLD) {
textView.setText(Constants.GOODBYE_WORLD);
}
else {
textView.setText(Constants.HELLO_WORLD);
}
}
public static void otherMethods() {
// other methods
}
}
并像这样在您的MainActivity
使用它
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.helloString);
Methods.changeText(textView)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.