Как я могу разделить функциональность MainActivity на другой класс для ясности? - PullRequest
1 голос
/ 29 марта 2019

У меня есть программа для 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) 

Ответы [ 4 ]

3 голосов
/ 29 марта 2019

У вас нулевой указатель, потому что вы не настроили представление содержимого для помощника по основным действиям.Использование и активность внутри другого не является правильным способом достижения вашей цели.

Если вы хотите иметь вспомогательный класс, вам не нужно расширять действие или объявлять поле, являющееся действием.Лучший способ - это использовать модель представления, которая является общим классом бэкэнда, используемым в шаблоне mvvm.Viewmodels позволяет отделить Logic от кода Activity.

Если вы хотите продолжить ваше дело, просто объявите обычный Java-класс и передайте ссылку Activity в конструктор этого класса.Что-то нравится в onCreate of Main Activity:

MainActivityHelper = new MainActivityHelper (this);

После этого вы можете вызывать методы своей деятельности внутри помощника (например, лайки findviewbyid).

Надеюсь, что это даст вам некоторые советы / помощь.

Приветствия.

1 голос
/ 29 марта 2019

вы получаете 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)
1 голос
/ 29 марта 2019

Вы не можете разделить действие на два класса, расширяющих класс AppCompatActivity, но у вас может быть вспомогательный класс или класс «Utils», который содержит набор статических функций, каждый из которых служит определенной цели.Таким образом, вы можете сделать код активности более читабельным, свернув его и перенеся части кода в класс помощника.

Кроме того, вы можете использовать ViewModel с LiveData, чтобы разделить логику «извлечения» данных и логику пользовательского интерфейса.Вы можете узнать больше об этом здесь: https://developer.android.com/jetpack/docs/guide

1 голос
/ 29 марта 2019

Вы не можете просто так нарушить активность. Я бы порекомендовал использовать фрагменты внутри действия, чтобы вы могли изолировать каждый фрагмент с помощью определенных фрагментов кода и просто сделать простой возврат к действию (на этом этапе действие представляет собой простой контейнер для склеивания всех фрагментов, служит посредник).

Пожалуйста, посмотрите на это Фрагменты Android .

Это может быть устаревшим, но это хорошая точка входа vogella .

...