شرح Shared Preference في الاندرويد

دروس التفضيل المشتركة مع مثال في Android Studio

تُستخدم التفضيلات المشتركة في Android لحفظ البيانات بناءً على زوج القيمة الرئيسية. إذا تعمقنا في فهم الكلمة: الوسائل المشتركة لتوزيع البيانات داخل والتفضيل يعني شيئًا مهمًا أو مفضلاً ، لذلك يتم مشاركة بيانات SharedPreferences والبيانات المفضلة.

يمكن استخدام التفضيل المشترك لحفظ نوع البيانات البدائي: سلسلة ، طويلة ، عدد صحيح ، عائم ومنطقي.

ما هو ملف التفضيل Preference ؟

قبل أن نبدأ في شرح التفضيلات المشتركة Shared Preference ، من المهم فهم ملف التفضيل.

ملف التفضيل Preference هو في الواقع ملف xml محفوظ في الذاكرة الداخلية للجهاز. يحتوي كل تطبيق على بعض البيانات المخزنة في الذاكرة في دليل بيانات / بيانات / اسم حزمة التطبيق ، على سبيل المثال data / data / com.abhiandroid.abhiapp ، لذلك كلما تم استدعاء وظيفة getSharedPreferences (اسم السلسلة ، الوضع int) ، تتحقق من صحة الملف إذا كان موجودًا أو لم يتم إنشاء ملف xml جديد باسم مر.


طريقتان لحفظ البيانات من خلال التفضيل المشترك:

هناك طريقتان مختلفتان لحفظ البيانات في Android من خلال التفضيلات المشتركة - أحدهما يستخدم التفضيلات القائمة على النشاط والآخر هو إنشاء تفضيلات مخصصة.

تفضيلات النشاط:

  • بالنسبة لتفضيلات النشاط ، يتعين على المطور استدعاء وظيفة getPreferences (الوضع int) المتوفرة في فئة النشاط
  • استخدمه فقط عند الحاجة إلى ملف تفضيل واحد في النشاط
  • لا يتطلب اسمًا لأنه سيكون ملف التفضيل الوحيد لهذا النشاط
  • لا يفضل المطور عادةً استخدام هذا حتى إذا كانوا بحاجة إلى ملف تفضيل واحد فقط في النشاط. يفضلون استخدام getSharedPreferences المخصص (اسم السلسلة ، الوضع int).

لاستخدام تفضيلات النشاط ، يجب على المطور استدعاء وظيفة getPreferences (الوضع int) المتوفرة في فئة النشاط. تستدعي وظيفة getPreferences (الوضع int) الوظيفة الأخرى المستخدمة لإنشاء تفضيلات مخصصة مثل getSharedPreferences (اسم السلسلة ، الوضع int). فقط لأن النشاط يحتوي على ملف تفضيلات واحد فقط ، لذا فإن وظيفة getPreferences (الوضع int) تقوم ببساطة بتمرير اسم فئة النشاط لإنشاء ملف تفضيل.

ملاحظة مهمة: تمت مناقشة الوضع في التفضيلات المخصصة.

التفضيلات المخصصة:

  • يحتاج المطور إلى استخدام getSharedPreferences (اسم السلسلة ، الوضع int) للتفضيلات المخصصة
  • يُستخدم في الحالات التي يكون فيها أكثر من ملف تفضيل واحد مطلوبًا في النشاط
  • يتم تمرير اسم ملف التفضيل في المعلمة الأولى

يمكن إنشاء التفضيلات المخصصة عن طريق استدعاء وظيفة getSharedPreferences (اسم السلسلة ، الوضع int) ، ويمكن استدعاؤها من أي مكان في التطبيق مع الإشارة إلى السياق. هنا الاسم هو أي اسم مفضل على سبيل المثال: مستخدم ، كتاب وما إلى ذلك ، ويستخدم الوضع لضبط نوع الخصوصية للملف.


الوضع ونوعه في التفضيل المشترك :

لإنشاء تفضيلات قائمة على النشاط أو تفضيلات مخصصة ، يتعين على المطور اجتياز الوضع للسماح للنظام بمعرفة خصوصية ملف التفضيل.

قبل أن نبدأ مناقشة موجزة عن السياق

السياق عبارة عن فئة مجردة تستخدم للحصول على معلومات عالمية في موارد تطبيقات Android مثل السلاسل والقيم والعناصر القابلة للرسم والأصول وما إلى ذلك. هنا يتم الإعلان عن الأوضاع والثابت النهائي الثابت في فئة السياق.

هناك ثلاثة أنواع من الوضع في التفضيلات المشتركة:

  1. Context.MODE_PRIVATE – default value (Not accessible outside of your application)
  2. Context.MODE_WORLD_READABLE – readable to other apps
  3. Context.MODE_WORLD_WRITEABLE – read/write to other apps

MODE_PRIVATE - إنه وضع افتراضي. MODE_PRIVATE يعني أنه عند إنشاء أي ملف تفضيل بالوضع الخاص ، فلن يكون الوصول إليه متاحًا خارج التطبيق الخاص بك. هذا هو الوضع الأكثر شيوعًا المستخدم.

MODE_WORLD_READABLE - إذا قام المطور بإنشاء ملف تفضيلات مشترك باستخدام الوضع العالمي للقراءة ، فيمكن قراءته من قبل أي شخص يعرف اسمه ، بحيث يمكن لأي تطبيق خارجي آخر قراءة بيانات تطبيقك بسهولة. نادرًا ما يتم استخدام هذا الوضع في التطبيق.

MODE_WORLD_WRITEABLE - إنه مشابه لوضع العالم المقروء ولكن مع كلا النوعين من الوصول ، أي القراءة والكتابة. لا يتم استخدام هذا الوضع مطلقًا في التطبيق بواسطة المطور.


مهمة توصي بها Google اصطلاح التسمية لملف التفضيل:

يرجى التأكد من اتباع توصيات Google مع إعطاء اسم الملف المفضل. توصي Google بإعطاء اسم كاسم حزمة التطبيق + الاسم المفضل.

على سبيل المثال: إذا كان اسم حزمة التطبيق الخاص بك هو اسم ملف com.abhiandroid.abhiappالتفضيل ، فقد يكون التفضيل هو com.abhiandroid.abhiapp.Userالمكان الذي com.abhiandroid.abhiapp.Userيوجد فيه اسم ملف التفضيل.


إنشاء تفضيل مشترك:

كما نوقش أعلاه ، لإنشاء تفضيلات مشتركة ، يحتاج المطور إلى استدعاء getPreferences (الوضع int) أو getSharedPreferences (String name، int mode) . تقوم كلتا الوظيفتين بإرجاع كائن SharedPreferences للتعامل مع الحفظ والحصول على القيم من ملف التفضيل.

SharedPreferences هي فئة فردية تعني أن هذه الفئة ستحتوي على كائن واحد فقط طوال دورة حياة التطبيق. ومع ذلك ، يمكن أن يكون هناك ملفات تفضيلات متعددة بحيث يمكن قراءة جميع ملفات التفضيلات وكتابتها باستخدام فئة SharedPreferences.


حفظ البيانات في SharedPreferences 

الخطوة 1:

لحفظ البيانات في SharedPreferences ، يحتاج المطور إلى استدعاء وظيفة التحرير () لفئة SharedPreferences التي تقوم بإرجاع كائن فئة المحرر .

الخطوة 2:

توفر فئة المحرر وظيفة مختلفة لحفظ بيانات الوقت الأولية. على سبيل المثال ، يحتوي المحرر على جميع وظائف البيانات الأولية بما في ذلك بيانات نوع السلسلة مثل putInt (String keyName ، قيمة int).

تنسيق الوظيفة الأولية الشائع هو: وضع + اسم النوع الأساسي (اسم مفتاح السلسلة ، قيمة النوع الأساسي)

الخطوه 3:

تأكد الآن من أن اسم المفتاح يجب أن يكون فريدًا لأي قيم تحفظها وإلا فسيتم تجاوزه. لحفظ القيم التي تضعها بالضبط في وظائف بدائية مختلفة ، يجب عليك استدعاء وظيفة الالتزام () للمحرر.


اقرأ البيانات أو احصل عليها من SharedPreferences

الخطوة 1: لقراءة البيانات أولاً ، يجب على المطور الحصول على مرجع لكائن SharedPreferences عن طريق استدعاء getPreferences (الوضع int) أو getSharedPreferences (String name، int mode) .

الخطوة 2: بعد ذلك ، يمكن للمطور الحصول على القيم باستخدام كائن SharedPreferences عن طريق استدعاء دالة نوع بدائي مختلفة تبدأ بـ get + Primitive Type name. هنا تحتوي كل وظيفة على معلمة إضافية لكل نوع أساسي كقيمة افتراضية في حالة عدم وجود قيمة مطابقة للمفتاح الذي تم تمريره.

على سبيل المثال ، للحصول على قيمة int المحفوظة ، فقط اتصل بوظيفة getInt ("GameScore" ، - 1) حيث تكون "GameScore" هي المفتاح و -1 هي القيمة الافتراضية في حالة عدم حفظ أي قيمة لـ GameScore.


إزالة البيانات أو مسح كافة البيانات

مماثلة لحفظ البيانات وجود وظيفة إزالة (مفتاح سلسلة) في SharedPreferences.Editorلإزالة البيانات الرئيسية القائمة معينة من ملف تفضيل

لمسح جميع البيانات ، ما عليك سوى الاتصال بالوظيفة امسح () المتوفرة بتنسيق SharedPreferences.Editor. تأكد من استدعاء طريقة الالتزام () لحفظ التغييرات. لذا فإن البيانات الواضحة لن تحذف ملف التفضيل أبدًا ولكنها تجعله فارغًا.


كود حفظ واسترجاع البيانات في التفضيل المشترك:

public static final String PREFS_GAME ="com.abhiandroid.abhiapp.GamePlay";
  public static final String GAME_SCORE= "GameScore";

  //======== Code to save data ===================

  SharedPreferences sp = getSharedPreferences(PREFS_GAME ,Context.MODE_PRIVATE);
  sp.edit().putInt(GAME_SCORE,100).commit();

  //========= Code to get saved/ retrieve data ==============

  SharedPreferences sp = getSharedPreferences(PREFS_GAME ,Context.MODE_PRIVATE);
  int sc  = sp.getInt(GAME_SCORE,0);
  Log.d("AbhiAndroid","achieved score  is "+ sc);

مثال التفضيل المشترك:

لنستخدم التفضيل المشترك لغرض أساسي للغاية وهو حفظ تفاصيل تسجيل الدخول لشخص ما ، مثل البريد الإلكتروني وكلمة المرور على جهازه. لذلك لا يتعين عليه إعادة إدخال تفاصيل تسجيل الدخول الخاصة به في كل مرة يفتح فيها التطبيق.

فيما يلي الناتج النهائي الذي سننشئه ونستخدمه "التفضيلات المشتركة" لحفظ تفاصيل تسجيل الدخول:

مثال التفضيل المشترك الناتج النهائي
الخطوة 1: أنشئ مشروعًا جديدًا وأنشئ نشاط تسجيل الدخول Activity_login. xml . في هذا إنشاء واجهة مستخدم تسجيل الدخول تطلب البريد الإلكتروني للمستخدم وكلمة المرور مع خيار تذكرني مربع الاختيار . أيضًا زر يعرض تسجيل الدخول أو التسجيل.

يوجد أدناه رمز واجهة مستخدم تسجيل الدخول الكامل Activity_login.xml

<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:gravity="center_horizontal"
  android:orientation="vertical"
  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="com.samplesharedpreferences.LoginActivity">

  <!-- Login progress -->
  <ProgressBar
  android:id="@+id/login_progress"
  style="?android:attr/progressBarStyleLarge"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_marginBottom="8dp"
  android:visibility="gone"/>

  <ScrollView
  android:id="@+id/login_form"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <LinearLayout
  android:id="@+id/email_login_form"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">

  <android.support.design.widget.TextInputLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <EditText
  android:id="@+id/email"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_email"
  android:inputType="textEmailAddress"
  android:maxLines="1"
  android:singleLine="true"/>

  </android.support.design.widget.TextInputLayout>

  <android.support.design.widget.TextInputLayout
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

  <EditText
  android:id="@+id/password"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:hint="@string/prompt_password"
  android:imeActionId="@+id/login"
  android:imeActionLabel="@string/action_sign_in_short"
  android:imeOptions="actionUnspecified"
  android:inputType="textPassword"
  android:maxLines="1"
  android:singleLine="true"/>

  </android.support.design.widget.TextInputLayout>

  <CheckBox
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:text="Remember Me"
  android:id="@+id/checkBoxRememberMe"/>

  <Button
  android:id="@+id/email_sign_in_button"
  style="?android:textAppearanceSmall"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_marginTop="16dp"
  android:text="@string/action_sign_in"
  android:textStyle="bold"/>

  </LinearLayout>
  </ScrollView>
  </LinearLayout>

الخطوة 2: الآن دعنا نبرمج نشاط تسجيل الدخول. جافا حيث سننشئ نموذج تسجيل الدخول. يوجد أدناه الرمز الكامل لـ LoginActivity. جافا مع شرح مدرج في التعليق.

package com.samplesharedpreferences;

  import android.animation.Animator;
  import android.animation.AnimatorListenerAdapter;
  import android.annotation.TargetApi;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.content.pm.PackageManager;
  import android.support.annotation.NonNull;
  import android.support.design.widget.Snackbar;
  import android.support.v7.app.AppCompatActivity;
  import android.app.LoaderManager.LoaderCallbacks;
  import android.content.ContentResolver;
  import android.content.CursorLoader;
  import android.content.Loader;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.AsyncTask;
  import android.os.Build.VERSION;
  import android.os.Build;
  import android.os.Bundle;
  import android.provider.ContactsContract;
  import android.text.TextUtils;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.inputmethod.EditorInfo;
  import android.widget.ArrayAdapter;
  import android.widget.AutoCompleteTextView;
  import android.widget.Button;
  import android.widget.CheckBox;
  import android.widget.EditText;
  import android.widget.TextView;

  import java.util.ArrayList;
  import java.util.List;

  import static android.Manifest.permission.READ_CONTACTS;

  /**
  * A login screen that offers login via email/password.
  */
  public class LoginActivity extends AppCompatActivity {


  // UI references.
  private EditText mEmailView;
  private EditText mPasswordView;

  private CheckBox checkBoxRememberMe;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_login);
  // Set up the login form.
  mEmailView = (EditText) findViewById(R.id.email);
  mPasswordView = (EditText) findViewById(R.id.password);
  mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
  @Override
  public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
  if (id == R.id.login || id == EditorInfo.IME_NULL) {
  attemptLogin();
  return true;
  }
  return false;
  }
  });

  Button mEmailSignInButton = (Button) findViewById(R.id.email_sign_in_button);
  mEmailSignInButton.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View view) {
  attemptLogin();
  }
  });

  checkBoxRememberMe = (CheckBox) findViewById(R.id.checkBoxRememberMe);
  //Here we will validate saved preferences
  if (!new PrefManager(this).isUserLogedOut()) {
  //user's email and password both are saved in preferences
  startHomeActivity();
  }

  }


  /**
  * Attempts to sign in or register the account specified by the login form.
  * If there are form errors (invalid email, missing fields, etc.), the
  * errors are presented and no actual login attempt is made.
  */
  private void attemptLogin() {

  // Reset errors.
  mEmailView.setError(null);
  mPasswordView.setError(null);

  // Store values at the time of the login attempt.
  String email = mEmailView.getText().toString();
  String password = mPasswordView.getText().toString();

  boolean cancel = false;
  View focusView = null;

  // Check for a valid password, if the user entered one.
  if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
  mPasswordView.setError(getString(R.string.error_invalid_password));
  focusView = mPasswordView;
  cancel = true;
  }

  // Check for a valid email address.
  if (TextUtils.isEmpty(email)) {
  mEmailView.setError(getString(R.string.error_field_required));
  focusView = mEmailView;
  cancel = true;
  } else if (!isEmailValid(email)) {
  mEmailView.setError(getString(R.string.error_invalid_email));
  focusView = mEmailView;
  cancel = true;
  }

  if (cancel) {
  // There was an error; don't attempt login and focus the first
  // form field with an error.
  focusView.requestFocus();
  } else {
  // save data in local shared preferences
  if (checkBoxRememberMe.isChecked())
  saveLoginDetails(email, password);
  startHomeActivity();
  }
  }

  private void startHomeActivity() {
  Intent intent = new Intent(this, HomeActivity.class);
  startActivity(intent);
  finish();
  }

  private void saveLoginDetails(String email, String password) {
  new PrefManager(this).saveLoginDetails(email, password);
  }


  private boolean isEmailValid(String email) {
  //TODO: Replace this with your own logic
  return email.contains("@");
  }

  private boolean isPasswordValid(String password) {
  //TODO: Replace this with your own logic
  return password.length() > 4;
  }
  }

الخطوة 3: قم بإنشاءفئة java جديدةلـ Shared PrefManager. يوجد أدناه رمز PrefManager.java

package com.samplesharedpreferences;

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

  /**
  * Class for Shared Preference
  */
  public class PrefManager {

  Context context;

  PrefManager(Context context) {
  this.context = context;
  }

  public void saveLoginDetails(String email, String password) {
  SharedPreferences sharedPreferences = context.getSharedPreferences("LoginDetails", Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = sharedPreferences.edit();
  editor.putString("Email", email);
  editor.putString("Password", password);
  editor.commit();
  }

  public String getEmail() {
  SharedPreferences sharedPreferences = context.getSharedPreferences("LoginDetails", Context.MODE_PRIVATE);
  return sharedPreferences.getString("Email", "");
  }

  public boolean isUserLogedOut() {
  SharedPreferences sharedPreferences = context.getSharedPreferences("LoginDetails", Context.MODE_PRIVATE);
  boolean isEmailEmpty = sharedPreferences.getString("Email", "").isEmpty();
  boolean isPasswordEmpty = sharedPreferences.getString("Password", "").isEmpty();
  return isEmailEmpty || isPasswordEmpty;
  }
  }

الخطوة 4: صمم واجهة مستخدم الصفحة الرئيسية البسيطة حيث سنعرض رسالة ترحيب مع عنوان بريده الإلكتروني المحفوظ في التفضيل المشترك. يوجد أدناه رمز content_home.xml

<?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  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"
  app:layout_behavior="@string/appbar_scrolling_view_behavior"
  tools:context="com.samplesharedpreferences.HomeActivity"
  tools:showIn="@layout/activity_home">

  <TextView
  android:id="@+id/textViewUser"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_centerInParent="true"
  android:gravity="center"
  android:text="Welcome"/>


  </RelativeLayout>

الخطوة 5: ملف البيان

تأكد من تعيين AndroidManifest.xml Intent Filter for Main و Launcher بداخل .LoginActivity لأنه عندئذٍ فقط سيتم فتح هذا النشاط أولاً.

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

  <!-- To auto-complete the email text field in the login form with the user's emails -->
  <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
  <uses-permission android:name="android.permission.READ_PROFILE"/>
  <uses-permission android:name="android.permission.READ_CONTACTS"/>

  <application
  android:allowBackup="true"
  android:icon="@mipmap/ic_launcher"
  android:label="@string/app_name"
  android:supportsRtl="true"
  android:theme="@style/AppTheme">
  <activity
  android:name=".LoginActivity"
  android:label="@string/app_name">
  <intent-filter>
  <action android:name="android.intent.action.MAIN"/>

  <category android:name="android.intent.category.LAUNCHER"/>
  </intent-filter>
  </activity>
  <activity
  android:name=".HomeActivity"
  android:label="@string/title_activity_home"
  android:theme="@style/AppTheme.NoActionBar">
  </activity>
  </application>

  </manifest>

انتاج:

الخطوة 1: الآن قم بتشغيل التطبيق في Emulator. سترى شاشة الإخراج أدناه

شاشة إخراج مثال التفضيلات المشتركة لتسجيل الدخول
الخطوة 2: املأ البريد الإلكتروني وكلمة المرور وانقر فوق مربع الاختيار تذكرني. في حالتنا ، قمنا بملء info@abhiandroid.com و abhiandroid.

التفضيلات المشتركة مثال تفاصيل تسجيل الدخول معبأ
الخطوة 3: سيعرض لك رسالة الترحيب مع معرف البريد الإلكتروني الخاص بك. أغلق الآن التطبيق وأعد فتحه. سترى نفس رسالة الترحيب وطبع عنوان بريدك الإلكتروني. لذلك قمنا هنا بتخزين عنوان بريدك الإلكتروني على جهازك نفسه باستخدام التفضيلات المشتركة.

تفاصيل تسجيل الدخول المفضلة المشتركة المحفوظة على الجهاز


أهمية :

أثناء تطوير التطبيق ، هناك العديد من المواقف التي نحتاج فيها إلى تخزين أو حفظ بعض البيانات في ملف. لذلك بدلاً من إنشاء ملفك الخاص ثم إدارته ، يوفر Android آلية لحفظ البيانات باستخدام SharedPreferences. لحفظ قدر ضئيل من البيانات ، يمكن استخدام SharedPreferences مثل اسم المستخدم وكلمة المرور للمستخدم ، ولكن إذا كانت هناك حاجة لحفظ كمية كبيرة من البيانات ، يفضل دائمًا حفظ البيانات باستخدام sqlite .