为了清楚起见,我如何将 MainActivity 功能拆分为另一个 class?
How can I split MainActivity functionality into an another class for clarity?
我有一个 android 程序,我希望能够将 MainActivity 中的功能拆分到多个文件中以保持我的代码井井有条,但我收到空对象引用错误。
为了演示错误,我创建了一个简单的程序,它只有一个 textView 和一个用于更改 textView 的按钮。单击按钮时会发生错误。我该如何解决这个问题,这样我才能得到帮助 class?
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 帮助程序设置内容视图。
在另一个内部使用 and Activity 不是到达 objective.
的正确方法
如果您想要一个助手 class,您不必扩展 Activity 或声明一个 Activity 字段。
最好的方法是使用一个视图模型,它是用于 mvvm 模式的通用后端 class。
Viewmodels 允许将逻辑与 Activity 代码分离。
如果你想继续你的案例只需声明一个普通的 Java class 并将 Activity 的引用传递给此 class 的构造函数。
在 Main Activity:
的 onCreate 中有类似这样的内容
MainActivityHelper = new MainActivityHelper(this);
之后,您可以在助手内部调用 activity 的方法(例如喜欢 findviewbyid)。
希望这能给你一些帮助 hints/help。
干杯。
你不能那样破坏 activity。我建议在 activity 中使用片段,这样你就可以将每个片段与特定的代码片段隔离开来,只需简单地回调 activity(此时,activity是一个简单的容器,用于粘合所有片段,充当调解器)。
请看看这个Android Fragments。
这个可能已经过时了,但它是一个很好的切入点 vogella。
您不能将 activity 拆分为两个扩展 AppCompatActivity class 的 class,但您可以使用助手 class 或 "Utils" class 它包含一组静态函数,每个函数都有特定的用途。通过这种方式,您可以通过最小化代码并将部分代码移动到助手 class.
来使 activity 代码更具可读性
此外,您可以将 ViewModel 与 LiveData 结合使用来分离数据 "Fetching" 逻辑和 UI 逻辑。您可以在此处了解更多相关信息:https://developer.android.com/jetpack/docs/guide
您正在获取 NPE
,因为您使用的是 findViewById
而未附加内容视图。
您可以创建一个单独的 class 并将此方法和所有其他方法放入其中:
Class 包含所有常量
public final class Constants {
public static final String HELLO_WORLD = "Hello World!";
public static final String GOODBYE_WORLD = "Goodbye world!";
}
Class 包含您所有的方法
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)
我有一个 android 程序,我希望能够将 MainActivity 中的功能拆分到多个文件中以保持我的代码井井有条,但我收到空对象引用错误。
为了演示错误,我创建了一个简单的程序,它只有一个 textView 和一个用于更改 textView 的按钮。单击按钮时会发生错误。我该如何解决这个问题,这样我才能得到帮助 class?
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 帮助程序设置内容视图。 在另一个内部使用 and Activity 不是到达 objective.
的正确方法如果您想要一个助手 class,您不必扩展 Activity 或声明一个 Activity 字段。 最好的方法是使用一个视图模型,它是用于 mvvm 模式的通用后端 class。 Viewmodels 允许将逻辑与 Activity 代码分离。
如果你想继续你的案例只需声明一个普通的 Java class 并将 Activity 的引用传递给此 class 的构造函数。 在 Main Activity:
的 onCreate 中有类似这样的内容MainActivityHelper = new MainActivityHelper(this);
之后,您可以在助手内部调用 activity 的方法(例如喜欢 findviewbyid)。
希望这能给你一些帮助 hints/help。
干杯。
你不能那样破坏 activity。我建议在 activity 中使用片段,这样你就可以将每个片段与特定的代码片段隔离开来,只需简单地回调 activity(此时,activity是一个简单的容器,用于粘合所有片段,充当调解器)。
请看看这个Android Fragments。
这个可能已经过时了,但它是一个很好的切入点 vogella。
您不能将 activity 拆分为两个扩展 AppCompatActivity class 的 class,但您可以使用助手 class 或 "Utils" class 它包含一组静态函数,每个函数都有特定的用途。通过这种方式,您可以通过最小化代码并将部分代码移动到助手 class.
来使 activity 代码更具可读性此外,您可以将 ViewModel 与 LiveData 结合使用来分离数据 "Fetching" 逻辑和 UI 逻辑。您可以在此处了解更多相关信息:https://developer.android.com/jetpack/docs/guide
您正在获取 NPE
,因为您使用的是 findViewById
而未附加内容视图。
您可以创建一个单独的 class 并将此方法和所有其他方法放入其中:
Class 包含所有常量
public final class Constants {
public static final String HELLO_WORLD = "Hello World!";
public static final String GOODBYE_WORLD = "Goodbye world!";
}
Class 包含您所有的方法
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)