为什么添加片段会破坏我的活动? [英] Why does my Activity get destroyed on adding a fragment?

查看:80
本文介绍了为什么添加片段会破坏我的活动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,在MainAcivity中编辑了一个方法之后,我遇到了RuntimeException.

So after editing a method in my MainAcivity, I'm getting a RuntimeException.

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tim.timapp
    /com.example.tim.timapp.MainActivity}: java.lang.IllegalStateException: 
    Activity has been destroyed

老实说,我不知道这是从哪里来的.在线搜索表明ChildFragmentManager的功能很大,但并没有给我提供适合我的解决方案.

I honestly have no idea where this is coming from. Searching online suggests that it's a big with the ChildFragmentManager, but doesn't give me a fix that works for me.

您知道我该怎么做才能解决此异常吗?

Any idea what I can do to fix this exception?

PS.如果您需要更多代码或信息,请告诉我.这个错误让我很沮丧,所以我可能在这里忽略了一些东西.

PS. If you need any more code or info, let me know. My mind is quite flustered by this error, so I might overlooked some stuff here.

完整日志:

03-30 21:19:47.910 24785-24785/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.tim.timapp, PID: 24785
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.tim.timapp/com.example.tim.timapp.MainActivity}: java.lang.IllegalStateException: Activity has been destroyed
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5417)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
    Caused by: java.lang.IllegalStateException: Activity has been destroyed
        at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1433)
        at android.app.BackStackRecord.commitInternal(BackStackRecord.java:687)
        at android.app.BackStackRecord.commit(BackStackRecord.java:663)
        at com.example.tim.timapp.MainActivity.DrawVariableFragments(MainActivity.java:271)
        at com.example.fragments.Settings.GeneralSettingsFragment.onCreateView(GeneralSettingsFragment.java:57)
        at android.app.Fragment.performCreateView(Fragment.java:2220)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:973)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1148)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1130)
        at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1953)
        at android.app.FragmentController.dispatchActivityCreated(FragmentController.java:152)
        at android.app.Activity.performCreateCommon(Activity.java:6232)
        at android.app.Activity.performCreate(Activity.java:6239)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
        at android.app.ActivityThread.-wrap11(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5417) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

MainActivity (很抱歉,这是一个WIP):

MainActivity (Sorry about the mess, it's a WIP):

很抱歉,整个文件超过了30.000个字符.
http://pastebin.com/XZ9k995G

Sorry about this, but I went over the 30.000 characters limit with the entire file.
http://pastebin.com/XZ9k995G

DBHandler (以前让我感到悲伤,所以可能与它有关):

DBHandler (Was giving me grief earlier, so might have something to do with it):

package com.example.tim.timapp;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;

import java.util.ArrayList;

public class DBHandler extends SQLiteOpenHelper {

    private static String tag = "TEST DBHandler";
    private static DBHandler sInstance;

    // Database Stuff
    private static final int DATABASE_VERSION = 6;
    private static final String DATABASE_NAME = "LinkDatabase.db";

    // Table Stuff
    private static final String TABLE_LinkTable = "LinkTable";
    private static final String TABLE_SettingsTable = "SettingsTable";

    // LinkTable Stuff
    private static final String LT_COLUMN_ID = "_id";
    private static final String LT_COLUMN_NAME = "name";
    private static final String LT_COLUMN_TAG = "tag";

    // SettingsTable Stuff
    private static final String ST_COLUMN_ID = "_id";
    private static final String ST_COLUMN_NAME = "name";
    private static final String ST_COLUMN_IP = "ip";
    private static final String ST_COLUMN_PORT = "port";
    private static final String ST_COLUMN_USERNAME = "username";
    private static final String ST_COLUMN_PASS = "pass";

    // Table Create Statements
    // LinkTable Create Statement
    private static final String CREATE_TABLE_LINKS =
            "CREATE TABLE " + TABLE_LinkTable + "(" +
            LT_COLUMN_ID + " INTEGER PRIMARY KEY, " +
            LT_COLUMN_NAME + " TEXT, " +
            LT_COLUMN_TAG + " TEXT" + ");";

    // SettingsTable Create Statement
    private static final String CREATE_TABLE_SETTINGS =
            "CREATE TABLE " + TABLE_SettingsTable + "(" +
            ST_COLUMN_ID + " INTEGER PRIMARY KEY, " +
            ST_COLUMN_NAME + " TEXT, " +
            ST_COLUMN_IP + " TEXT, " +
            ST_COLUMN_PORT + " TEXT, " +
            ST_COLUMN_USERNAME + " TEXT, " +
            ST_COLUMN_PASS + " TEXT" + ");";

    // TODO: 28-Mar-16 DON"T FORGET TO UPDATE
    // Don't forget to update this when adding a new table.
    private static final ArrayList<String> createTablesArray = new ArrayList<String>() {{add(CREATE_TABLE_LINKS); add(CREATE_TABLE_SETTINGS);}};
    private static final ArrayList<String> tableNamesArray = new ArrayList<String>() {{add(TABLE_LinkTable); add(TABLE_SettingsTable);}};




    public ArrayList<String> tagArray;

    public static synchronized DBHandler getInstance(Context context) {
        if (sInstance == null) {
            Log.d(tag, "sInstance == null");
            sInstance = new DBHandler(context.getApplicationContext());
        }
        return sInstance;
    }

    private DBHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        for (String s : createTablesArray) {
            db.execSQL(s);
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        for (String s : tableNamesArray) {
            db.execSQL("DROP TABLE IF EXISTS " + s);
        }
        onCreate(db);
    }

    public ArrayList<String> returnArray(String base, String column) {
        SQLiteDatabase db;
        db = getWritableDatabase();
        String TABLENAME;
        if (base.equalsIgnoreCase("StuffManager")) {
            TABLENAME = TABLE_LinkTable;
        } else if (base.equalsIgnoreCase("GeneralSettings")) {
            TABLENAME = TABLE_SettingsTable;
        } else {
            Log.e(tag, "String Base not recognised");
            return null;
        }

        String query = "SELECT * FROM " + TABLENAME + " WHERE 1";

        Cursor c = db.rawQuery(query, null);
        c.moveToFirst();

        ArrayList<String> tempArray = new ArrayList<>();

        int i = 0;
        while(!c.isAfterLast()){
            if(c.getString(c.getColumnIndex(column)) != null){
                tempArray.add(i, c.getString(c.getColumnIndex(column)));
            } else {
                Log.e(tag, "String Column not recognised");
                return null;
            }
            c.moveToNext();
            i++;
        }
        c.close();
        if (db != null && db.isOpen()) {
            db.close();
        }
        return tempArray;
    }

    // *** --------- ***
    //
    // All methods for the SETTINGS_TABLES
    //
    // *** --------- ***

    public void addSettings(String name, String ip, String port, String username, String pass) {
        ContentValues values = new ContentValues();
        values.put(ST_COLUMN_NAME, name);
        values.put(ST_COLUMN_IP, ip);
        values.put(ST_COLUMN_PORT, port);
        values.put(ST_COLUMN_USERNAME, username);
        values.put(ST_COLUMN_PASS, pass);
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.insert(TABLE_SettingsTable, null, values);
        db.close();
    }

    public void updateSettings(int id, String name, String ip, String port, String username, String pass) {
        ContentValues values = new ContentValues();
        values.put(ST_COLUMN_NAME, name);
        values.put(ST_COLUMN_IP, ip);
        values.put(ST_COLUMN_PORT, port);
        values.put(ST_COLUMN_USERNAME, username);
        values.put(ST_COLUMN_PASS, pass);
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.update(TABLE_SettingsTable, values, "_id=" + id, null);
        db.close();
    }

    public void deleteSettings(String name) {
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_SettingsTable + " WHERE " + ST_COLUMN_NAME + "=\"" + name + "\";");
        db.close();
    }

    public void deleteAllSettings() {
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_SettingsTable + " WHERE 1");
        db.close();
    }

    public float settingsTableSize() {
        SQLiteDatabase db;
        db = getReadableDatabase();
        float  amount = DatabaseUtils.queryNumEntries(db, TABLE_SettingsTable);
        db.close();
        return amount;
    }

    public ArrayList<String> settingsNameArrayMethod() {
        SQLiteDatabase db;
        db = getWritableDatabase();
        String query = "SELECT * FROM " + TABLE_SettingsTable + " WHERE 1";

        Cursor c = db.rawQuery(query, null);
        c.moveToFirst();

        int i = 0;

        ArrayList<String> nameArray = new ArrayList<>();

        while (!c.isAfterLast()) {
            if (c.getString(c.getColumnIndex("name")) != null) {
                nameArray.add(i, c.getString(c.getColumnIndex("name")));
            }
            c.moveToNext();
            i++;
        }
        c.close();
        db.close();
        return nameArray;
    }


    // *** --------- ***
    //
    // All methods for the LINK_TABLES
    //
    // *** --------- ***

    public void addStuffLink(String name, String tag) {
        ContentValues values = new ContentValues();
        values.put(LT_COLUMN_NAME, name);
        values.put(LT_COLUMN_TAG, tag);
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.insert(TABLE_LinkTable, null, values);
        db.close();
    }

    public Bundle updateStuffLink(int id, String name, String tag) {
        ContentValues values = new ContentValues();
        values.put(LT_COLUMN_NAME, name);
        values.put(LT_COLUMN_TAG, tag);
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.update(TABLE_LinkTable, values, "_id=" + id, null);

        db.close();
        ArrayList<String> nameArray = stuffLinksNameArrayMethod();
        ArrayList<String> tagArray = tagArrayMethod();

        Bundle bundle = new Bundle();
        bundle.putStringArrayList("nameArray", nameArray);
        bundle.putStringArrayList("tagArray", tagArray);
        return bundle;
    }

    public void deleteStuffLink(String name) {
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_LinkTable + " WHERE " + LT_COLUMN_NAME + "=\"" + name + "\";");
        db.close();
    }

    public void deleteAllStuffLinks() {
        SQLiteDatabase db;
        db = getWritableDatabase();
        db.execSQL("DELETE FROM " + TABLE_LinkTable + " WHERE 1");
        db.close();
    }

    public ArrayList<String> stuffLinksNameArrayMethod(){
        SQLiteDatabase db;
        db = getWritableDatabase();
        String query = "SELECT * FROM " + TABLE_LinkTable + " WHERE 1";

        Cursor c = db.rawQuery(query, null);
        c.moveToFirst();

        int i = 0;

        ArrayList<String> nameArray = new ArrayList<>();
        tagArray = new ArrayList<>();

        while(!c.isAfterLast()){
            if(c.getString(c.getColumnIndex("name")) != null){
                nameArray.add(i, c.getString(c.getColumnIndex("name")));
                tagArray.add(i, c.getString(c.getColumnIndex("tag")));
            }
            c.moveToNext();
            i++;
        }
        c.close();
        db.close();
        return nameArray;
    }

    public ArrayList<String> tagArrayMethod() {
        stuffLinksNameArrayMethod();
        return tagArray;
    }

    public float stuffTableSize(){
        SQLiteDatabase db;
        db = getReadableDatabase();
        float  amount = DatabaseUtils.queryNumEntries(db, TABLE_LinkTable);
        db.close();
        return amount;
    }

}

常规设置片段

package com.example.fragments.Settings;

import android.app.AlertDialog;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import com.example.fragments.MainFragments.DialogFragments.GeneralSettingsInitialInputDialog;
import com.example.fragments.MainFragments.VariableFragments.GeneralSettingsEmptyFragment;
import com.example.fragments.MainFragments.VariableFragments.GeneralSettingsVariableFragment;
import com.example.fragments.MainFragments.VariableFragments.StuffManagerVariableFragment;
import com.example.tim.timapp.DBHandler;
import com.example.tim.timapp.MainActivity;
import com.example.tim.timapp.R;

import java.util.ArrayList;

public class GeneralSettingsFragment extends Fragment {

    DBHandler dbHandler;
    MainActivity ma = new MainActivity();
    private static Menu optionsMenu;
    public static boolean hideDeleteAllButton = false;
    LinearLayout linearLayout;
    View rootView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        setHasOptionsMenu(true);
        super.onCreate(savedInstanceState);
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_generalsettings, container, false);
        linearLayout = (LinearLayout) rootView.findViewById(R.id.FragmentContainerGeneralSettings);

        if (linearLayout == null) {
            Log.e("GMF", "Layout is null");
        } else if (linearLayout.getChildCount() == 0) {
            GeneralSettingsInitialInputDialog GSIID = new GeneralSettingsInitialInputDialog();
            GSIID.show(getFragmentManager(), "dialog");
            hideDeleteAllButton = true;
        } else {
            hideDeleteAllButton = false;
        }
        ma.DrawVariableFragments("GeneralSettings", "draw");
        return rootView;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.stuffmanager_actionbuttons, menu);
        optionsMenu = menu;
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        optionsMenu.findItem(R.id.removeAllButton).setVisible(!hideDeleteAllButton);
        super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.addButton:
                GeneralSettingsInitialInputDialog GSIID = new GeneralSettingsInitialInputDialog();
                GSIID.show(getFragmentManager(), "dialog");
                return true;
            case R.id.removeAllButton:
                dbHandler = DBHandler.getInstance(getActivity());
                final ArrayList<String> nameArray = dbHandler.settingsNameArrayMethod();
                final FragmentManager fm = getFragmentManager();
                AlertDialog.Builder removeAllDialog = new AlertDialog.Builder(getActivity())
                        .setTitle("Delete all?")
                        .setMessage("Are you sure you want to delete all your devices? This is irreversible.")
                        .setIcon(R.drawable.ic_delete_black)
                        .setPositiveButton("Delete", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                dbHandler.deleteAllSettings();
                                for (String name : nameArray){
                                    fm.beginTransaction().remove(fm.findFragmentByTag(name)).commit();
                                }
                                fm.executePendingTransactions();
                                // TODO: 30-Mar-16 Add "No devices created" screen like stuffmanager
                                hideDeleteAllButton = true;
                                getActivity().invalidateOptionsMenu();
                            }
                        })
                        .setNegativeButton("Cancel", null);
                removeAllDialog.show();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }
}

推荐答案

MainActivity ma = new MainActivity();

这在Android中无效.您无法创建这样的Activity实例,因为它实际上并未附加到Android进程中. MainActivity的这个实例不会逐步执行任何生命周期方法,这就是为什么您看到活动已停止的错误的原因.它从未真正开始过.

This isn't valid in Android. You can't create an instance of an Activity like this because it isn't actually attached to the Android processes. This instance of MainActivity isn't going to step through any of the lifecycle methods, which is why you're seeing the error that the activity has been stopped. It was never actually started.

相反,请删除对MainActivity的引用,因为将这样的引用保留在片段中是一种不好的做法.每当您需要片段中的MainActivity实例时,请使用以下示例:

Instead, remove this reference to MainActivity, as it's bad practice to keep references like this around in your fragment. Any time you need an instance of MainActivity inside a fragment, use the following example:

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    // ...

    MainActivity ma = (MainActivity) getActivity();
    ma.DrawVariableFragments("GeneralSettings", "draw");

    // ...

}

这篇关于为什么添加片段会破坏我的活动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆