【问题标题】:App force closes when leaving SettingsActivity离开 SettingsActivity 时应用强制关闭
【发布时间】:2013-07-04 14:39:17
【问题描述】:

这是我的第二个问题(已经回答):Creating SharedPreferences object inside Fragment

在弄清楚如何在静态 Fragment 类中创建 SharedPreferences 对象后,我开始使用它从 SettingsActivity 检索用户设置的值以设置 TextEdits 值。应用程序编译没有错误,并在模拟器上很好地启动,显示默认值(我还没有输入设置)。设置打开没有任何问题。但是,当我在 ActionBar 上单击“向上”时,应用程序挂起并强制关闭。之后我无法打开它 - 它一直强制关闭,直到清除应用程序数据。

看起来像在第一个应用程序打开 Fragment 静态类中的 SharedPreference 方法设置默认数据(如果他们发现 null 时应该这样做)并且在输入设置并使用“up”返回之后(我没有更改任何值,只是保留首选项 xml 中定义的默认值),应用程序将该默认值保存到 SharedPreferences 中,然后尝试检索它以在 Fragments 中设置 TextEdits。还有就是关门的地方。

奇怪的是,当我使用 /* */ cmets 在静态 Fragment 类(公共静态类 Dzien 扩展 Fragment)内的 switch case 中“关闭”所有 ifs 时,应用程序工作,进入,离开设置,这是可能的在不崩溃的情况下刷过所有片段。更奇怪的是,如果在最后一种情况下“开启” 5...:

case 5: { // Piątek
                lekcja1.setText(getString(R.string.mat));
                lekcja2.setText(getString(R.string.mat));
                lekcja3.setText(getString(R.string.bio));
                lekcja4.setText(getString(R.string.pol));
                lekcja5.setText(getString(R.string.pol));
                lekcja6.setText(getString(R.string.edb));
                if (settings.getBoolean(WDZ, false)) {
                    lekcja7.setText(getString(R.string.wdz));
                } else {
                    lekcja7.setText(getString(R.string.brak));
                }
                lekcja8.setText(getString(R.string.brak));
                lekcja9.setText(getString(R.string.brak));
                break;
            }

...在离开它们并转到第 5 个片段(使用 WDZ 的地方)时不会使设置崩溃。我可以切换 WDZ 复选框,它会在相应的 Fragment 中反映它的状态。

我不知道什么可能导致崩溃,因为如果情况 1、2、3 和 4 中的块是正确的 - 唯一的区别是它们使用 getInt() 而不是 getBoolean()。尽管如此,在导航到相应的 Fragment 后,应用还是会崩溃。

以下是来源:

MainActivity.class(底部的Fragment类)

package pl.konpon96.planlekcji;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Calendar;
import java.util.Locale;

public class MainActivity extends FragmentActivity {

//public static final String APP_PREFERENCES = "app_preferences";

//public static final String GRUPA_ANGIELSKI = "grupa_angielski_list";
public static final String GRUPA_JEZYKOWA = "grupa_jezykowa_list";
public static final String GRUPA_INFORMATYKA = "grupa_informatyka_list";
public static final String WDZ = "wdz_checkbox";
//public static final String PODSWIETLANIE_LEKCJI = "podswietlanie_lekcji_checkboxs";

/**
 * The {@link android.support.v4.view.PagerAdapter} that will provide
 * fragments for each of the sections. We use a
 * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
 * will keep every loaded fragment in memory. If this becomes too memory
 * intensive, it may be best to switch to a
 * {@link android.support.v4.app.FragmentStatePagerAdapter}.
 */
SectionsPagerAdapter mSectionsPagerAdapter;

/**
 * The {@link ViewPager} that will host the section contents.
 */
ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    // Create the adapter that will return a fragment for each of the three
    // primary sections of the app.
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mSectionsPagerAdapter);

    //Ustawianie domyślnej zakładki w zależności od dnia

    Calendar timeNow = Calendar.getInstance();

    switch (timeNow.get(Calendar.DAY_OF_WEEK)) {
        case Calendar.MONDAY: {
            mViewPager.setCurrentItem(0, true);
            break;
        }
        case Calendar.TUESDAY: {
            mViewPager.setCurrentItem(1, true);
            break;
        }
        case Calendar.WEDNESDAY: {
            mViewPager.setCurrentItem(2, true);
            break;
        }
        case Calendar.THURSDAY: {
            mViewPager.setCurrentItem(3, true);
            break;
        }
        case Calendar.FRIDAY: {
            mViewPager.setCurrentItem(4, true);
            break;
        }
        case Calendar.SATURDAY: {
            mViewPager.setCurrentItem(0, true);
            Toast sobotaToast = Toast.makeText(getApplicationContext(),
                    "Jest sobota - nie ma zajęć", Toast.LENGTH_SHORT);
            sobotaToast.show();
            break;
        }
        case Calendar.SUNDAY: {
            mViewPager.setCurrentItem(0, true);
            Toast niedzielaToast = Toast.makeText(getApplicationContext(),
                    "Jest niedziela - nie ma zajęć", Toast.LENGTH_SHORT);
            niedzielaToast.show();
            break;
        }


    }

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override

public boolean onOptionsItemSelected(MenuItem item) {
    // Handle item selection
    switch (item.getItemId()) {
        case R.id.action_settings: {
            Intent settingsActivity = new Intent(getBaseContext(), SettingsActivity.class);
            startActivity(settingsActivity);
            return true;
        }
        case R.id.action_dzwonki: {
            Intent dzwonkiActivity = new Intent(getBaseContext(), DzwonkiActivity.class);
            startActivity(dzwonkiActivity);
            return true;
        }
        default:
            return super.onOptionsItemSelected(item);
    }
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
 * one of the sections/tabs/pages.
 */
public class SectionsPagerAdapter extends FragmentPagerAdapter {

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        // getItem is called to instantiate the fragment for the given page.
        // Return a DummySectionFragment (defined as a static inner class
        // below) with the page number as its lone argument.
        Fragment fragment = new Dzien();
        Bundle args = new Bundle();
        args.putInt(Dzien.ARG_SECTION_NUMBER, position + 1);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public int getCount() {
        // Show 5 total pages.
        return 5;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        Locale l = Locale.getDefault();
        switch (position) {
            case 0:
                return getString(R.string.title_pon).toUpperCase(l);
            case 1:
                return getString(R.string.title_wt).toUpperCase(l);
            case 2:
                return getString(R.string.title_sr).toUpperCase(l);
            case 3:
                return getString(R.string.title_czw).toUpperCase(l);
            case 4:
                return getString(R.string.title_pt).toUpperCase(l);
        }
        return null;
    }
}

/**
 * A dummy fragment representing a section of the app, but that simply
 * displays dummy text.
 */
/*
public static class DummySectionFragment extends Fragment {

     * The fragment argument representing the section number for this
     * fragment.

    public static final String ARG_SECTION_NUMBER = "section_number";

    public DummySectionFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main_dummy, container, false);
        TextView dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
        dummyTextView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));
        return rootView;
    }
}
*/
public static class Dzien extends Fragment {

    public static final String ARG_SECTION_NUMBER = "section_number";

    public Dzien() {
    }

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

        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        TextView lekcja1 = (TextView) rootView.findViewById(R.id.lekcja1);
        TextView lekcja2 = (TextView) rootView.findViewById(R.id.lekcja2);
        TextView lekcja3 = (TextView) rootView.findViewById(R.id.lekcja3);
        TextView lekcja4 = (TextView) rootView.findViewById(R.id.lekcja4);
        TextView lekcja5 = (TextView) rootView.findViewById(R.id.lekcja5);
        TextView lekcja6 = (TextView) rootView.findViewById(R.id.lekcja6);
        TextView lekcja7 = (TextView) rootView.findViewById(R.id.lekcja7);
        TextView lekcja8 = (TextView) rootView.findViewById(R.id.lekcja8);
        TextView lekcja9 = (TextView) rootView.findViewById(R.id.lekcja9);

        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getActivity());

        switch (getArguments().getInt(ARG_SECTION_NUMBER)) {
            case 1: { // Poniedziałek
                lekcja1.setText(getString(R.string.wos));
                lekcja2.setText(getString(R.string.mat));
                lekcja3.setText(getString(R.string.ang));
                lekcja4.setText(getString(R.string.gw));
                lekcja5.setText(getString(R.string.his));
                lekcja6.setText(getString(R.string.wf));
                lekcja7.setText(getString(R.string.pp));
                if (settings.getInt(GRUPA_INFORMATYKA, 1) == 1) {
                    lekcja8.setText(getString(R.string.inf));
                } else {
                    lekcja8.setText(getString(R.string.brak));
                }
                lekcja9.setText(getString(R.string.brak));
                break;
            }
            case 2: { // Wtorek
                lekcja1.setText(getString(R.string.mat));
                lekcja2.setText(getString(R.string.pp));
                lekcja3.setText(getString(R.string.rel));
                lekcja4.setText(getString(R.string.wf));
                lekcja5.setText(getString(R.string.pol));
                lekcja6.setText(getString(R.string.pol));
                if (settings.getInt(GRUPA_JEZYKOWA, 1) == 2) {
                    lekcja7.setText(getString(R.string.ros));
                    lekcja8.setText(getString(R.string.ros));
                } else {
                    lekcja7.setText(getString(R.string.brak));
                    lekcja8.setText(getString(R.string.brak));
                }
                lekcja9.setText(getString(R.string.brak));
                break;
            }
            case 3: { // Sroda
                lekcja1.setText(getString(R.string.his));
                lekcja2.setText(getString(R.string.wf));
                lekcja3.setText(getString(R.string.mat));
                lekcja4.setText(getString(R.string.rel));
                lekcja5.setText(getString(R.string.ang));
                if (settings.getInt(GRUPA_JEZYKOWA, 1) == 1) {
                    lekcja6.setText(getString(R.string.niem));
                    lekcja7.setText(getString(R.string.niem));
                } else {
                    lekcja6.setText(getString(R.string.brak));
                    lekcja7.setText(getString(R.string.brak));
                }
                lekcja8.setText(getString(R.string.brak));
                lekcja9.setText(getString(R.string.brak));
                break;
            }
            case 4: { // Czwartek
                lekcja1.setText(getString(R.string.mat));
                lekcja2.setText(getString(R.string.fiz));
                lekcja3.setText(getString(R.string.wok));
                lekcja4.setText(getString(R.string.geo));
                lekcja5.setText(getString(R.string.ang));
                lekcja6.setText(getString(R.string.chem));
                if (settings.getInt(GRUPA_INFORMATYKA, 1) == 2) {
                    lekcja7.setText(getString(R.string.inf));
                } else if (((settings.getInt(GRUPA_INFORMATYKA, 1) == 2)) && ((settings.getInt(GRUPA_JEZYKOWA, 1) != 3))) {
                    lekcja7.setText(getString(R.string.brakpre));
                } else {
                    lekcja7.setText(getString(R.string.brak));
                }
                if (settings.getInt(GRUPA_JEZYKOWA, 1) == 3) {
                    lekcja8.setText(getString(R.string.por));
                    lekcja9.setText(getString(R.string.por));
                }
                break;
            }
            case 5: { // Piątek
                lekcja1.setText(getString(R.string.mat));
                lekcja2.setText(getString(R.string.mat));
                lekcja3.setText(getString(R.string.bio));
                lekcja4.setText(getString(R.string.pol));
                lekcja5.setText(getString(R.string.pol));
                lekcja6.setText(getString(R.string.edb));
                if (settings.getBoolean(WDZ, false)) {
                    lekcja7.setText(getString(R.string.wdz));
                } else {
                    lekcja7.setText(getString(R.string.brak));
                }
                lekcja8.setText(getString(R.string.brak));
                lekcja9.setText(getString(R.string.brak));
                break;
            }


        }

        return rootView;
    }
}
}

SettingsActivity.class - 删除预编译的首选项片段后有点混乱 - 我正在使用已弃用的 API,因为它不会使用平板电脑 UI。

package pl.konpon96.planlekcji;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.view.MenuItem;

/**
 * A {@link PreferenceActivity} that presents a set of application settings. On
 * handset devices, settings are presented as a single list. On tablets,
 * settings are split by category, with category headers shown to the left of
 * the list of settings.
 * <p/>
 * See <a href="http://developer.android.com/design/patterns/settings.html">
 * Android Design: Settings</a> for design guidelines and the <a
 * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
 * API Guide</a> for more information on developing a Settings UI.
 */
@SuppressWarnings("deprecation")
public class SettingsActivity extends PreferenceActivity {

private static final boolean ALWAYS_SIMPLE_PREFS = true;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setupActionBar();

    addPreferencesFromResource(R.xml.pref_general);

    bindPreferenceSummaryToValue(findPreference("grupa_angielski_list"));
    bindPreferenceSummaryToValue(findPreference("grupa_jezykowa_list"));
    bindPreferenceSummaryToValue(findPreference("grupa_informatyka_list"));
}

/**
 * Set up the {@link android.app.ActionBar}, if the API is available.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() { // Przycisk UP na ActionBar
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) { // Akcja użytkownika - przycisk UP
    switch (item.getItemId()) {
        case android.R.id.home:
            // This ID represents the Home or Up button. In the case of this
            // activity, the Up button is shown. Use NavUtils to allow users
            // to navigate up one level in the application structure. For
            // more details, see the Navigation pattern on Android Design:
            //
            // http://developer.android.com/design/patterns/navigation.html#up-vs-back
            //
            // TODO: If Settings has multiple levels, Up should navigate up
            // that hierarchy.
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}


/**
 * Shows the simplified settings UI if the device configuration if the
 * device configuration dictates that a simplified, single-pane UI should be
 * shown.
 */

/**
 * {@inheritDoc}
 */
@Override
public boolean onIsMultiPane() {
    return isXLargeTablet(this) && !isSimplePreferences(this);
}

/**
 * Helper method to determine if the device has an extra-large screen. For
 * example, 10" tablets are extra-large.
 */
private static boolean isXLargeTablet(Context context) {
    return (context.getResources().getConfiguration().screenLayout
            & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
}

/**
 * Determines whether the simplified settings UI should be shown. This is
 * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
 * doesn't have newer APIs like {@link PreferenceFragment}, or the device
 * doesn't have an extra-large screen. In these cases, a single-pane
 * "simplified" settings UI should be shown.
 */
private static boolean isSimplePreferences(Context context) {
    return ALWAYS_SIMPLE_PREFS
            || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
            || !isXLargeTablet(context);
}

/**
 * A preference value change listener that updates the preference's summary
 * to reflect its new value.
 */
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object value) {
        String stringValue = value.toString();

        if (preference instanceof ListPreference) {
            // For list preferences, look up the correct display value in
            // the preference's 'entries' list.
            ListPreference listPreference = (ListPreference) preference;
            int index = listPreference.findIndexOfValue(stringValue);

            // Set the summary to reflect the new value.
            preference.setSummary(
                    index >= 0
                            ? listPreference.getEntries()[index]
                            : null);

        } else {
            // For all other preferences, set the summary to the value's
            // simple string representation.
            preference.setSummary(stringValue);
        }
        return true;
    }
};

/**
 * Binds a preference's summary to its value. More specifically, when the
 * preference's value is changed, its summary (line of text below the
 * preference title) is updated to reflect the value. The summary is also
 * immediately updated upon calling this method. The exact display format is
 * dependent on the type of preference.
 *
 * @see #sBindPreferenceSummaryToValueListener
 */
private static void bindPreferenceSummaryToValue(Preference preference) {
    // Set the listener to watch for value changes.
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    // Trigger the listener immediately with the preference's
    // current value.
    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
            PreferenceManager
                    .getDefaultSharedPreferences(preference.getContext())
                    .getString(preference.getKey(), ""));
}

}

首选项 pref_general.xml 文件:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory android:title="@string/pref_header_personalizacja">

    <ListPreference
            android:key="grupa_jezykowa_list"
            android:title="@string/pref_title_grupa_jezykowa"
            android:defaultValue="1"
            android:entries="@array/pref_grupa_jezykowa_list_titles"
            android:entryValues="@array/pref_grupa_jezykowa_values"
            android:negativeButtonText="@null"
            android:positiveButtonText="@null"/>


    <ListPreference
            android:key="grupa_angielski_list"
            android:title="@string/pref_title_grupa_angielski"
            android:defaultValue="1"
            android:entries="@array/pref_grupa_angielski_list_titles"
            android:entryValues="@array/pref_grupa_angielski_values"
            android:negativeButtonText="@null"
            android:positiveButtonText="@null"/>

    <ListPreference
            android:key="grupa_informatyka_list"
            android:title="@string/pref_title_grupa_informatyka"
            android:defaultValue="1"
            android:entries="@array/pref_grupa_informatyka_list_titles"
            android:entryValues="@array/pref_grupa_informatyka_values"
            android:negativeButtonText="@null"
            android:positiveButtonText="@null"/>

    <CheckBoxPreference
            android:key="wdz_checkbox"
            android:title="@string/pref_title_wdz"
            android:summary="@string/pref_description_wdz"
            android:defaultValue="false"/>

</PreferenceCategory>

这是第一次打开应用后模拟器的logcat,输入设置然后返回:

https://dl.dropboxusercontent.com/u/6200994/logcat.txt

【问题讨论】:

  • zapomniałeś o najważniejszym ... gdzie są logi z logcat ?一个inna rzecz ... dane przechowywane w kodzie?一个jak będziesz chciał szybko zmienić?
  • 你有 Logcat 吗?
  • @Selvin To bardzo wczesna wersja, daleka od gotowej。 Na razie muszę mieć przygotowane wszystkie inne narzędzia, jak np SharedPreferences。 Później zajmę się rozłożeniem wyświetlania tekstów na oddzielną klasę aby poprawić czytelność i przeniesieniem całego planu do xml albo SQLite。

标签: java android crash android-fragments sharedpreferences


【解决方案1】:

好的,现在一切都清楚了。 SettingsActivity 自动保存的 SharedPreferences 是 String 类型的,所以应该使用 getString() 而不是 getInt()。更重要的是,如果有两个字符串要比较,应该使用 .equal() 方法而不是 == 运算符。

例如...:

if (settings.getInt(GRUPA_INFORMATYKA, 1) == 1) {
                lekcja8.setText(getString(R.string.inf));
            } else {
                lekcja8.setText(getString(R.string.brak));
            }

...应该是:

if (settings.getString(GRUPA_INFORMATYKA, "1").equals("1")) {
                lekcja8.setText(getString(R.string.inf));
            } else {
                lekcja8.setText(getString(R.string.brak));
            }

感谢那些提醒我有关 logcat 的人。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多