为什么我的Activity在添加片段时会被破坏?

时间:2016-03-30 21:28:06

标签: java android android-fragments android-activity

所以在我的MainAcivity中编辑一个方法后,我得到一个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很重要,但是没有给我一个适合我的修复。

知道我可以做些什么来解决这个异常吗?

PS。如果您需要更多代码或信息,请告诉我们。我的想法因为这个错误而非常慌张,所以我可能会忽略这里的一些东西。

完整日志:

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):

对此抱歉,但我对整个文件超过了30.000个字符的限制 http://pastebin.com/XZ9k995G

DBHandler (早些时候给我悲伤,所以可能与它有关):

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;
    }

}

GeneralSettingsFragment

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);
        }
    }
}

1 个答案:

答案 0 :(得分:3)

MainActivity ma = new MainActivity();

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

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

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

    // ...

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

    // ...

}