Эмулятор выдает исключение (android studio) при вызове функции - PullRequest
1 голос
/ 01 августа 2020

Я кодирую игру в студии android, и она работает нормально, но она начала вылетать, когда я переместил функцию в другой класс.

Я сделал это, чтобы использовать везде, имея его только один раз и не копировать вставку в каждый класс, который мне нужен.

Я проверил в Google, как решить эту проблему, но ничего не работает, ошибка связана с "getExternalFilesDir" или "openFileOutput", возвращающим null, я думаю .

Вот класс с двумя функциями (выполняющими в основном одно и то же), но которые я не могу использовать.

import android.media.MediaScannerConnection;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class WriteUserData extends AppCompatActivity {
    
    public void writeToFile(String data, String file) {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(file + ".txt", MODE_PRIVATE));
            outputStreamWriter.write(data);
            outputStreamWriter.close();
        }
        catch (IOException e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }
    }

    public void saveFile(String fileName, String addText){
        try {
            // Creates a file in the primary external storage space of the
            // current application.
            // If the file does not exists, it is created.
            File newFile = new File(this.getExternalFilesDir(null), fileName + ".txt");
            if (!newFile.exists())
                newFile.createNewFile();

            // Adds a line to the file
            BufferedWriter writer = new BufferedWriter(new FileWriter(newFile, true /*append*/));
            writer.write(addText);
            writer.close();
            // Refresh the data so it can seen when the device is plugged in a
            // computer. You may have to unplug and replug the device to see the
            // latest changes. This is not necessary if the user should not modify
            // the files.
            MediaScannerConnection.scanFile(this,
                    new String[]{newFile.toString()},
                    null,
                    null);
        } catch (IOException e) {
            Log.e("ReadWriteFile", "Error while trying to add text in " + fileName + ".txt");
        }
    }

}

и есть место, где я пытаюсь вызвать функции но вызывает сбой эмулятора (я удалил код 'import'), чтобы вам было легче понять.

    private boolean showStats = true;
    private final static long Interval = 30;
    private Handler handler = new Handler();
    private int flashDisplay = 0;

    @SuppressLint("SetTextI18n")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game_over);

        // change game over screen on click
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if(showStats){
                            getStats();
                        }
                        flashDisplay++;
                    }
                });
            }
        }, 0, Interval);
    }

    private static void bring(){
        WriteUserData saveScore = new WriteUserData();
        saveScore.saveFile("userdata", "ThisTextWork");
        saveScore.writeToFile("ThisTextWorkToo", "config");
    }

    @SuppressLint("SetTextI18n")
    private void getStats(){
        bring();
    }
}

Это ошибка:

java .lang .NullPointerException: попытка вызвать виртуальный метод 'java .io.FileOutputStream android .content.Context.openFileOutput (java .lang.String, int)' для ссылки на нулевой объект Blockquote

1 Ответ

0 голосов
/ 01 августа 2020

Вы неправильно понимаете, как работают действия.

public class WriteUserData extends AppCompatActivity {

Вы расширяете класс Activity, поэтому WriteUserData также является действием. В этом случае он должен называться так - WriteUserDataActivity.

Однако, глядя на то, что вы здесь делаете:

WriteUserData saveScore = new WriteUserData();

Это не то, как вы должны использовать деятельность. Он должен быть создан с намерением и startActivity(), см. Здесь:

https://developer.android.com/training/basics/firstapp/starting-activity

То, что вы хотели сделать, это переместить logi c для открытия файл в отдельном классе, чтобы избежать дублирования кода. Это здорово, но это должно быть не с действием. Вместо этого вы должны использовать класс Utils / Helper. Ваш класс не должен ничего расширять и должен иметь частный конструктор:

public class WriteUserDataUtils { 
    private WriteUserDataUtils() { 
        // utils classes shouldn't be instanced
    }
    ... 
}

После этого измените методы внутри него на static:

public static void writeToFile(String data, String file) {
    ...
}

public static void saveFile(String fileName, String addText) {
    ...
}

Наконец, причина вы расширили Activity, так это то, что вам нужно Context для некоторых вещей (например, для открытия файлового потока). Это можно легко исправить, передав его в качестве параметра:

public static void writeToFile(String data, String file, Context context) {
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput(file + ".txt", MODE_PRIVATE));
    ...
}

public static void saveFile(String fileName, String addText, Context context){
    try {
        File newFile = new File(context.getExternalFilesDir(null), fileName + ".txt");
    ...
}

После рефакторинга в класс utils вы можете вызвать его из операции следующим образом:

private static void bring(){
    WriteUserDataUtils.saveFile("userdata", "ThisTextWork", this);
    WriteUserDataUtils.writeToFile("ThisTextWorkToo", "aconfig", this);
}

Пусть я знаю, нужны ли вам дополнительные разъяснения.

...