【问题标题】:Android SharedPreferences not removed until app is restartedAndroid SharedPreferences 直到应用程序重新启动才被删除
【发布时间】:2017-02-03 17:20:40
【问题描述】:

我被这个问题困住了。 在我的应用程序中,我使用 SharedPrefManager 作为单例类,以保留一些“会话”信息。在这个简单的示例应用程序中,我只保存用户名和一个布尔值,指示用户是否已登录,如果已登录则跳过登录屏幕,否则显示它。 启动应用程序时,在启动画面之后,LoginActivity 会启动。 此时,如果用户之前已经登录过(以后没有注销,即isuseradded SharedPreferences 变量的布尔值为true),用户将被重定向到MainActivity,否则他会看到登录表单,他可以在其中插入用户名和密码并向远程服务器发出 REST API 请求。 如果登录正确,MainActivity 将启动并简单地显示用户名,取自远程登录 REST API 调用获得的响应 JSON。 现在,这是我的问题:我想实现一个简单的注销功能,该功能删除(或更改,如在此测试应用程序中)由 SharedPreferences 存储的所有信息并将用户带回 LoginActivity。 但是当我单击注销时,SharedPreferences 的值仅在 MainActivity 中更新,而在 LoginActivity 中它们保持与以前相同,因此当用户被重定向到 LoginActivity 时,isusedadded 共享首选项仍然是 true,并且用户被重定向回 MainActivity。 但是 SharedPrefManager 类是单例的,所以它的值在应用程序的每个部分都应该是相同的,因为它只有一个实例存在,那我为什么会有这种行为呢?

您可以通过下载完整的应用代码here 并使用这些凭据登录来测试应用:

用户名: 52346

密码: 32fjueM1(区分大小写)

下面是我的代码。

App.java:

package mypackage.sharedprefapp;

import android.app.Application;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;

public class App extends Application
    {
     private RequestQueue mRequestQueue;
     private static App mInstance;

     @Override
     public void onCreate()
        {
         super.onCreate();

         mInstance = this;
        }

     public static synchronized App getInstance()
        {
         return mInstance;
        }

     // This method returns the queue containing GET/POST requests
     public RequestQueue getRequestQueue()
        {
         if(mRequestQueue == null)
            {
             mRequestQueue = Volley.newRequestQueue(getApplicationContext());
            }

         return mRequestQueue;
        }

     // This method adds a GET/POST request to the queue of requests
     public <T> void addToRequestQueue(Request<T> req)
        {
         getRequestQueue().add(req);
        }
    }

SplashActivity.java

package mypackage.sharedprefapp;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class SplashActivity extends AppCompatActivity
    {
     @Override
     protected void onCreate(Bundle savedInstanceState)
        {
         super.onCreate(savedInstanceState);

         Intent intent = new Intent(this, LoginActivity.class);
         startActivity(intent);

         finish();
        }
    }

LoginActivity.java

package mypackage.sharedprefapp;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

public class LoginActivity extends AppCompatActivity
    {
     private static final String TAG = "LoginActivity";

     Button loginButton;
     EditText userIDInput, passwordInput;
     TextView loginErrorMsg, title;
     LinearLayout bgLayout;

     SharedPrefManager sharedPrefManager;

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

         sharedPrefManager = SharedPrefManager.getInstance(this);

         Log.i("HERE", "LoginActivity onCreate: "+sharedPrefManager.isUserAdded());
        }    

     @Override
     protected void onResume()
        {
         super.onResume();

         sharedPrefManager = SharedPrefManager.getInstance(this);

         Log.i("HERE", "LoginActivity onResume: "+sharedPrefManager.getUserName());

         // if the user is already logged in
         if(sharedPrefManager.isUserAdded())
            {
             Log.i(TAG, "User is logged in");

             // if the device is connected to the internet
             if(Utils.isDeviceOnline(this))
                {
                 Intent intent = new Intent(this, MainActivity.class);
                 startActivity(intent);

                 finish();
                }

             // if the device is offline
             else
                {
                 Log.i(TAG, "Internet connection is not available");
                }
            }

         // if the user is not logged in
         else
            {
             Log.i(TAG, "User is NOT logged in");

             setContentView(R.layout.activity_login);

             title = (TextView) findViewById(R.id.title);
             loginErrorMsg = (TextView) findViewById(R.id.login_errorText);
             userIDInput = (EditText) findViewById(R.id.login_id_paziente);
             passwordInput = (EditText) findViewById(R.id.login_password);
             loginButton = (Button) findViewById(R.id.login_submitButton);
             bgLayout = (LinearLayout) findViewById(R.id.login_parentLayout);

             // Bind a custom click listener to the login button
             loginButton.setOnClickListener(new LoginButtonClickListener(this));

             // Bind a custom click listener to the background layout
             // so that the soft keyboard is dismissed when clicking on the background
             bgLayout.setOnClickListener(new LoginBackgroundClickListener());
            }
        }
    }

LoginButtonClickListener.java

package mypackage.sharedprefapp;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;

public class LoginButtonClickListener implements View.OnClickListener
    {
     private Context context;
     private SharedPrefManager sharedPrefManager;

     public LoginButtonClickListener(Context c)
        {
         this.context = c;
        }

     @Override
     public void onClick(View v)
        {
         sharedPrefManager = SharedPrefManager.getInstance(context);

         // if internet connection is available
         if(Utils.isDeviceOnline(context))
            {
             // Verify login credentials from DB
             doLogin();
            }

         else {}
        }

     // check login data with REST API
     private void doLogin()
        {
         final String paziente_id = ((EditText)((Activity)context).findViewById(R.id.login_id_paziente)).getText().toString();
         final String paziente_password = ((EditText)((Activity)context).findViewById(R.id.login_password)).getText().toString();

         StringRequest stringRequest = new StringRequest
            (
             Request.Method.POST,
             "http://www.stefanopace.net/iCAREServer/api/v1/index.php/login",

             new Response.Listener<String>()
                {
                 @Override
                 public void onResponse(String s)
                    {
                     try
                        {
                         JSONObject obj = new JSONObject(s);

                         if(!obj.getBoolean("error"))
                            {
                             String name = obj.getString("nome");

                             sharedPrefManager.addUser(name);

                             Intent intent = new Intent(context, MainActivity.class);
                             context.startActivity(intent);
                            }

                         else
                            {
                             Toast.makeText(context, "Error on JSON response", Toast.LENGTH_LONG).show();
                            }
                        }

                     catch(JSONException e)
                        {
                         e.printStackTrace();
                        }
                    }
                },

             new Response.ErrorListener()
                {
                 @Override
                 public void onErrorResponse(VolleyError volleyError)
                    {
                     Toast.makeText(context, volleyError.getMessage(), Toast.LENGTH_LONG).show();
                    }
                })

            {
             @Override
             protected Map<String, String> getParams() throws AuthFailureError
                {
                 Map<String, String> params = new HashMap<>();
                 params.put("id_paziente", paziente_id);
                 params.put("password", paziente_password);

                 return params;
                }
            };

         App.getInstance().addToRequestQueue(stringRequest);
        }
    }

LoginBackgroundClickListener.java

package mypackage.sharedprefapp;

import android.view.View;

public class LoginBackgroundClickListener implements View.OnClickListener
    {
     @Override
     public void onClick(View v)
        {
         Utils.hideSoftKeyboard(v);
        }
    }

MainActivity.java

package mypackage.sharedprefapp;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;  

public class MainActivity extends AppCompatActivity
    {
     private static final String TAG = "MainActivity";

     TextView personName;

     SharedPrefManager sharedPrefManager;    

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

         sharedPrefManager = SharedPrefManager.getInstance(this);

         setContentView(R.layout.activity_main);

         personName = (TextView) findViewById(R.id.person_name);

         Log.i(TAG, "Value: "+sharedPrefManager.isUserAdded());

         personName.setText(sharedPrefManager.getUserName());
        }

     @Override
     protected void onResume()
        {
         super.onResume();

         sharedPrefManager = SharedPrefManager.getInstance(this);

         Log.w("MainActivity", "onResume");
        }

     @Override
     public boolean onCreateOptionsMenu(Menu menu)
        {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.mainmenu, menu);

         return true;
        }

     @Override
     public boolean onOptionsItemSelected(MenuItem item)
        {
         switch(item.getItemId())
            {
             // Logout button has been pressed
             case R.id.logout_action:
                {
                 Log.i("Logout pressed", "Logout button has been pressed!");

                 final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
                 alertDialogBuilder.setMessage("Are you sure you want to logout?");

                 alertDialogBuilder.setPositiveButton
                    (
                     "Yes",
                     new DialogInterface.OnClickListener()
                        {
                         @Override
                         public void onClick(DialogInterface arg0, int arg1)
                            {
                             boolean success = sharedPrefManager.removeDataFromSharedPreference();

                             // if the operation is OK
                             if(success)
                                {
                                 // go to the login activity
                                 Intent intent = new Intent(MainActivity.this, LoginActivity.class);
                                 startActivity(intent);

                                 finish();
                                }

                             else
                                {
                                 Toast.makeText(getApplicationContext(), "Error during logout", Toast.LENGTH_LONG).show();
                                }
                            }
                        }
                    );

                 alertDialogBuilder.setNegativeButton
                    (
                     "No",
                     new DialogInterface.OnClickListener()
                        {
                         @Override
                         public void onClick(DialogInterface arg0, int arg1)
                            {}
                        }
                    );

                 AlertDialog alertDialog = alertDialogBuilder.create();
                 alertDialog.show();

                 return true;
                }
            }

         return super.onOptionsItemSelected(item);
        }
    }

SharedPrefManager.java

package mypackage.sharedprefapp;

import android.content.Context;
import android.content.SharedPreferences;

public final class SharedPrefManager
    {
     private static final String TAG = "SharedPrefManager";

     private SharedPreferences sharedPreferences;
     private SharedPreferences.Editor editor;

     private static SharedPrefManager mInstance;

     private static final String SHARED_PREF = "sharedprefs";

     private static final String KEY_IS_USER_ADDED = "isuseradded";
     public static final String KEY_USER_NAME = "username";

     private SharedPrefManager(Context context)
        {
         sharedPreferences = context.getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE);
         editor = sharedPreferences.edit();

         sharedPreferences.registerOnSharedPreferenceChangeListener(new LocalSharedPreferencesChangeListener());
        }

     public static SharedPrefManager getInstance(Context context)
        {
         if(mInstance == null)
            {
             mInstance = new SharedPrefManager(context);
            }

         return mInstance;
        }

     // add an user to the shared preferences
     public boolean addUser(String name)
        {
         editor.putString(KEY_USER_NAME, name);
         editor.putBoolean(KEY_IS_USER_ADDED, true);

         return editor.commit();
        }

     public boolean removeDataFromSharedPreference()
        {
         editor.putString(KEY_USER_NAME, "HELLO");
         editor.putBoolean(KEY_IS_USER_ADDED, false);

         return editor.commit();
        }    

     public String getUserName()
        {
         return sharedPreferences.getString(KEY_USER_NAME, "");
        }

     public boolean isUserAdded()
        {
         return sharedPreferences.getBoolean(KEY_IS_USER_ADDED, false);
        }
    }

Utils.java

package mypackage.sharedprefapp;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.view.inputmethod.InputMethodManager;    

public class Utils
    {
     public static void hideSoftKeyboard(View view)
        {
         InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
         inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
        }


     // This method checks if the device is connected to the Internet
     public static boolean isDeviceOnline(final Context context)
        {
         final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

         if(connectivityManager != null)
            {
             final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();

             boolean isOnline = (networkInfo != null && networkInfo.isConnectedOrConnecting());

             if(!isOnline)
                {
                 AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);

                 alertDialog.setCancelable(false);
                 alertDialog.setTitle("Error");
                 alertDialog.setMessage("Internet is not available");

                 alertDialog.setPositiveButton("Try again", new DialogInterface.OnClickListener()
                    {
                     public void onClick(DialogInterface dialog, int which)
                        {
                         // Reload the Activity
                         Intent intent = ((Activity) context).getIntent();
                         ((Activity) context).finish();
                         context.startActivity(intent);
                        }
                    });

                 alertDialog.show();
                }

             return isOnline;
            }

         return false;
        }
    }

LocalSharedPreferencesChangeListener

package mypackage.sharedprefapp;

import android.content.SharedPreferences;
import android.util.Log;

public class LocalSharedPreferencesChangeListener implements SharedPreferences.OnSharedPreferenceChangeListener
    {
     @Override
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
        {
         Log.i("HERE", key);
        }
    }

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".LoginActivity"
    android:padding="0dp">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollView"
        android:layout_gravity="center_horizontal">

        <LinearLayout
            android:id="@+id/login_parentLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:clickable="true">

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@mipmap/ic_launcher"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="50dp"
                android:layout_marginBottom="30dp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:layout_gravity="center_horizontal"
                android:gravity="center_horizontal"
                android:layout_marginBottom="30dp"
                android:singleLine="false"
                android:padding="5dp"
                android:textSize="30sp" />

            <EditText
                android:id="@+id/login_id_paziente"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:inputType="number"
                android:ems="10"
                android:hint="Username"
                android:textColor="@android:color/black"
                android:textColorHint="@android:color/darker_gray"
                android:singleLine="true"
                android:minLines="1"
                android:gravity="center_horizontal"
                android:layout_marginLeft="50dp"
                android:layout_marginRight="50dp"
                android:focusableInTouchMode="true"
                android:focusable="true" />

            <EditText
                android:id="@+id/login_password"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:hint="Password"
                android:textColorHint="@android:color/darker_gray"
                android:inputType="textPassword"
                android:ems="10"
                android:textColor="@android:color/black"
                android:maxLines="1"
                android:singleLine="true"
                android:layout_marginTop="20dp"
                android:gravity="center_horizontal"
                android:layout_marginLeft="50dp"
                android:layout_marginRight="50dp"
                android:focusableInTouchMode="true"
                android:focusable="true" />

            <TextView
                android:id="@+id/login_errorText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Login error"
                android:textColor="@android:color/holo_red_dark"
                android:layout_gravity="center_horizontal"
                android:gravity="center_horizontal"
                android:singleLine="false"
                android:padding="5dp"
                android:textSize="20sp"
                android:layout_margin="10dp"
                android:visibility="invisible" />

            <Button
                android:id="@+id/login_submitButton"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Login"
                android:textSize="20sp"
                android:layout_marginLeft="50dp"
                android:layout_marginRight="50dp" />

        </LinearLayout>

    </ScrollView>

</LinearLayout>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="mypackage.sharedprefapp.MainActivity">

    <TextView
        android:id="@+id/person_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:textSize="25sp"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

splashscreen.xml(在可绘制资源文件夹中)

<?xml version="1.0" encoding="utf-8"?>

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@android:color/holo_green_dark"/>

    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher"/>
    </item>

</layer-list>

ma​​inmenu.xml(在 res/menu 资源文件夹中)

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item android:id="@+id/logout_action"
        android:title="Logout"
        app:showAsAction="always" />

</menu>

styles.xml

<resources>

    ...

    <style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
        <item name="android:windowBackground">@drawable/splashscreen</item>
    </style>

</resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="mypackage.sharedprefapp">

    <!-- Needs internet to connect to Google Services -->
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Permission to check internet connection state -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name=".SplashActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme" />

        <activity
            android:name=".LoginActivity"
            android:label="@string/app_name"
            android:process=":other_process"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme">
            <intent-filter>
                <action android:name="android.intent.action.LOGIN_ACTION" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

    </application>

</manifest>

build.gradle(模块:app)

dependencies {
    ...
    compile 'com.android.volley:volley:1.0.0'
}

谢谢!

【问题讨论】:

  • 在 SharedPrefManager.java 中创建一个方法公共类型并添加此代码 SharedPreferences.Editor.clear().commit();并在注销时调用。
  • 您可以在注销操作中添加它 editor.putBoolean("KEY_IS_USER_ADDED", false);
  • 在我的 SharedPrefManager.java 中的 removeDataFromSharedPreference 方法中,我有这个在注销时调用的代码:editor.clear(); return editor.commit(); 其中编辑器定义为 SharedPreferences.Editor .是一样的吗?如果是,它对我不起作用:(或者更好,它起作用,但前提是我重新启动应用程序。
  • @ashish 我也试过了,不适合我:(
  • 当您注销时,应用程序现在的行为是什么?

标签: android login sharedpreferences logout


【解决方案1】:

我自己发现了问题...它不喜欢 sharedPrefManager.removeDataFromSharedPreference(); 方法从内部调用 new DialogInterface.OnClickListener()

我把它放在代码的另一部分,它工作了。

【讨论】:

    【解决方案2】:

    我更改了我的代码以便只有一个 SharedPrefManager 类的实例。 这是我的 App 单例类:

    public class App extends Application
        {
         private static App mInstance;
         private SharedPrefManager sharedPrefManager;
    
         @Override
         public void onCreate() {
             super.onCreate();
             mInstance = this;
             sharedPrefManager = new SharedPrefManager(this);
            }
    
         public SharedPrefManager getSharedPrefManager(){
             return sharedPrefManager;
            }
    
         public static synchronized App getInstance(){
             return mInstance;
            }
        }
    

    然后我通过调用从其他类获取实例

    SharedPrefManager sharedPrefManager = App.getInstance().getSharedPrefManager();
    

    现在,有了这个变化,onSharedPreferenceChanged() 事件只触发一次,所以这比以前好,但是“延迟”行为仍然存在......我的意思是,即使我使用 editor.clear();和 editor.commit();方法,值已更新,但只有在我关闭并再次打开应用程序时才能看到它们。

    【讨论】:

      【解决方案3】:

      @Ciammarica 您可以在单击注销按钮时调用此代码,希望这可以帮助您..您可以在注销按钮中设置布尔值 false..

      SessionManager.setUserLoggedIn(YourActivity.this, false); SessionManager.clearAppCredential(YourActivity.this);

      【讨论】:

        【解决方案4】:

        只需调用 editor.clear();editor.commit(); 足以从共享偏好中删除所有数据。

        【讨论】:

        • 是的,我在每个论坛都读过这个,但我不明白为什么我的应用还不够:(
        【解决方案5】:

        SharedPreferences是永久存储,可以清除

        SharedPreferences.Editor.clear().commit();
        

        替代解决方案 您想在应用关闭后清除整个值,请尝试Application singleton class

        【讨论】:

        • 也许我在管理 SharedPreferences 时犯了一些错误...我使用 SharedPrefManager 类,在其中声明了一个 SharedPreferences 对象和一个 Editor。然后,在我的代码中,我使用该管理器来使用 SharedPreferences。
        【解决方案6】:

        因为onResume,你不断地实例化一个新的SharedPrefManager

        sharedPrefManager = new SharedPrefManager(this);

        修改您的SharedPrefManager,使其始终只提供一个实例,或者确保您在返回 LoginActivity 时引用的是同一个对象。

        【讨论】:

        • 好的,我试一试,我会告诉你的!谢谢
        • 将我的代码更改为拥有一个 SharedPrefManager 实例。 App 单例类:public class App extends Application { private static App mInstance; private SharedPrefManager sharedPrefManager; @Override public void onCreate() { super.onCreate(); mInstance = this; sharedPrefManager = new SharedPrefManager(this); } public SharedPrefManager getSharedPrefManager(){ return sharedPrefManager; } public static synchronized App getInstance(){ return mInstance; } }
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-29
        • 1970-01-01
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        • 2014-11-26
        • 1970-01-01
        相关资源
        最近更新 更多