الفرق بين المراجعتين ل"ReactNative/appstate"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط
 
(3 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:الواجهة البرمجية AppState في React Native}}</noinclude>  
+
<noinclude>{{DISPLAYTITLE:الواجهة AppState في React Native}}</noinclude>  
 
تُستخدم الواجهة البرمجيّة <code>AppState</code> لإخبار المستخدم بوجود التّطبيق في الواجهة الأماميّة (foreground)، أو الخلفية (background)، وإشعاره عند تغيّر ذلك.  
 
تُستخدم الواجهة البرمجيّة <code>AppState</code> لإخبار المستخدم بوجود التّطبيق في الواجهة الأماميّة (foreground)، أو الخلفية (background)، وإشعاره عند تغيّر ذلك.  
  
سطر 5: سطر 5:
 
__toc__
 
__toc__
 
== حالات التطبيق ==
 
== حالات التطبيق ==
 
+
يكون التطبيق في إحدى الحالات التالية:
 
* النّشطة <code>active</code>: يعمل التّطبيق في الواجهة الأماميّة.
 
* النّشطة <code>active</code>: يعمل التّطبيق في الواجهة الأماميّة.
 
* في الخلفيّة <code>background</code>: يعمل التطبيق في الخلفية، وتعني أنّ المستخدم في إحدى الحالات التالية:
 
* في الخلفيّة <code>background</code>: يعمل التطبيق في الخلفية، وتعني أنّ المستخدم في إحدى الحالات التالية:
سطر 18: سطر 18:
 
يمكن معرفة الحالة الحاليّة من خلال تفحّص الخاصيّة <code>AppState.currentState</code>، والتي تُحدَّث دائمًا، وتكون قيمتها <code>null</code> عند بداية التشغيل ثم تستعيدها <code>AppState</code> عبر الجسر.  
 
يمكن معرفة الحالة الحاليّة من خلال تفحّص الخاصيّة <code>AppState.currentState</code>، والتي تُحدَّث دائمًا، وتكون قيمتها <code>null</code> عند بداية التشغيل ثم تستعيدها <code>AppState</code> عبر الجسر.  
  
* مثال لمكوِّن دالّة (Function Component)
+
* [https://snack.expo.dev/@hsoubwiki/appstate-function-component-example مثال لمكوِّن دالّة (Function Component)]
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
import React, { useRef, useState, useEffect } from "react";
 
import React, { useRef, useState, useEffect } from "react";
 
import { AppState, StyleSheet, Text, View } from "react-native";
 
import { AppState, StyleSheet, Text, View } from "react-native";
+
 
 
const AppStateExample = () => {
 
const AppStateExample = () => {
 const appState = useRef(AppState.currentState);
+
  const appState = useRef(AppState.currentState);
 const [appStateVisible, setAppStateVisible] = useState(appState.current);
+
  const [appStateVisible, setAppStateVisible] = useState(appState.current);
+
 
 useEffect(() => {
+
  useEffect(() => {
   AppState.addEventListener("change", _handleAppStateChange);
+
    const subscription = AppState.addEventListener("change", nextAppState => {
+
      if (
   return () => {
+
        appState.current.match(/inactive|background/) &&
     AppState.removeEventListener("change", _handleAppStateChange);
+
        nextAppState === "active"
   };
+
      ) {
 +
        console.log("App has come to the foreground!");
 +
      }
 +
 
 +
      appState.current = nextAppState;
 +
      setAppStateVisible(appState.current);
 +
      console.log("AppState", appState.current);
 +
    });
 +
 
 +
    return () => {
 +
      subscription.remove();
 +
    };
 
   }, []);
 
   }, []);
+
 
 const _handleAppStateChange = (nextAppState) => {
+
   return (
   if (
+
    <View style={styles.container}>
     appState.current.match(/inactive|background/) &&
+
      <Text>Current state is: {appStateVisible}</Text>
     nextAppState === "active"
+
    </View>
   ) {
 
     console.log("App has come to the foreground!");
 
   }
 
 
   appState.current = nextAppState;
 
   setAppStateVisible(appState.current);
 
   console.log("AppState", appState.current);
 
   };
 
 
 return (
 
   <View style={styles.container}>
 
     <Text>Current state is: {appStateVisible}</Text>
 
   </View>
 
 
   );
 
   );
 
};
 
};
+
 
 
const styles = StyleSheet.create({
 
const styles = StyleSheet.create({
 container: {
+
  container: {
   flex: 1,
+
    flex: 1,
   justifyContent: "center",
+
    justifyContent: "center",
   alignItems: "center",
+
    alignItems: "center",
 
   },
 
   },
 
});
 
});
+
 
export default AppStateExample;  
+
export default AppStateExample;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* مثال لمكوِّن صنف (Class Component)
+
* [https://snack.expo.dev/@hsoubwiki/appstate-class-component-example مثال لمكوِّن صنف (Class Component)]
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
import React, { Component } from "react";
 
import React, { Component } from "react";
 
import { AppState, StyleSheet, Text, View } from "react-native";
 
import { AppState, StyleSheet, Text, View } from "react-native";
+
 
 
class AppStateExample extends Component {
 
class AppStateExample extends Component {
 state = {
+
  state = {
   appState: AppState.currentState
+
    appState: AppState.currentState
 
   };
 
   };
+
 
 componentDidMount() {
+
  componentDidMount() {
   AppState.addEventListener("change", this._handleAppStateChange);
+
    this.appStateSubscription = AppState.addEventListener(
 +
      "change",
 +
      nextAppState => {
 +
        if (
 +
          this.state.appState.match(/inactive|background/) &&
 +
          nextAppState === "active"
 +
        ) {
 +
          console.log("App has come to the foreground!");
 +
        }
 +
        this.setState({ appState: nextAppState });
 +
      }
 +
    );
 
   }
 
   }
+
 
 componentWillUnmount() {
+
  componentWillUnmount() {
   AppState.removeEventListener("change", this._handleAppStateChange);
+
    this.appStateSubscription.remove();
 
   }
 
   }
+
 
 _handleAppStateChange = nextAppState => {
+
   render() {
   if (
+
    return (
     this.state.appState.match(/inactive|background/) &&
+
      <View style={styles.container}>
     nextAppState === "active"
+
        <Text>Current state is: {this.state.appState}</Text>
   ) {
+
      </View>
     console.log("App has come to the foreground!");
+
    );
   }
 
   this.setState({ appState: nextAppState });
 
   };
 
 
 render() {
 
   return (
 
     <View style={styles.container}>
 
       <Text>Current state is: {this.state.appState}</Text>
 
     </View>
 
   );
 
 
   }
 
   }
 
}
 
}
+
 
 
const styles = StyleSheet.create({
 
const styles = StyleSheet.create({
 container: {
+
  container: {
   flex: 1,
+
    flex: 1,
   justifyContent: "center",
+
    justifyContent: "center",
   alignItems: "center"
+
    alignItems: "center"
 
   }
 
   }
 
});
 
});
+
 
export default AppStateExample;  
+
export default AppStateExample;
 
</syntaxhighlight>عند عدم الرغبة برؤية انتقال <code>AppState</code> من الحالة <code>active</code> إلى الحالة <code>inactive</code> على منصة iOS يمكن إزالة متغير الحالة واستخدام القيمة <code>appState.current</code>.
 
</syntaxhighlight>عند عدم الرغبة برؤية انتقال <code>AppState</code> من الحالة <code>active</code> إلى الحالة <code>inactive</code> على منصة iOS يمكن إزالة متغير الحالة واستخدام القيمة <code>appState.current</code>.
  
سطر 119: سطر 118:
  
 
=== <code>change</code> ===
 
=== <code>change</code> ===
يُطلَق هذا الحدث عند تغيّر حالة التّطبيق، ويستدعى المُنصت (listener) مع أحد قيم '''[[ReactNative/appstate#app-states|حالات التطبيق]]''' الحاليّة (التي ذكرناها في الأعلى).  
+
يُطلَق هذا الحدث عند تغيّر حالة التّطبيق، ويستدعى المُنصت (listener) مع أحد قيم [[ReactNative/appstate#app-states|حالات التطبيق]] الحاليّة (التي ذكرناها في الأعلى).  
  
 
=== <code>memoryWarning</code> ===
 
=== <code>memoryWarning</code> ===
سطر 132: سطر 131:
 
== التوابع ==
 
== التوابع ==
  
=== <code>()addEventListener</code> ===
+
=== <code>‎addEventListener()</code> ===
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
addEventListener(type, handler);
 
addEventListener(type, handler);
 
</syntaxhighlight>يضيف معالجًا لتغيرات AppState وذلك بالتنصّت للحدث من النوع <code>change</code> وربطه مع المعالج (handler).
 
</syntaxhighlight>يضيف معالجًا لتغيرات AppState وذلك بالتنصّت للحدث من النوع <code>change</code> وربطه مع المعالج (handler).
  
'''ملاحظة:''' أصبحت AppState صنفًا فرعيًّا من NativeEventEmitter، لذا يمكن استبدال التابعين <code>addEventListener</code> و <code>removeEventListener</code> بالتابعين <code>addListener</code> و <code>listener.remove()</code> مباشرةً. ستحدث تغيرات مفاجئة لأنّ اسم التابع والحدث مختلفان (يجب أن تكون الأحداث <code>addListener</code> فريدةً بشكلٍ عامٍّ).
+
=== <code>‎removeEventListener()</code> ===
 
 
=== <code>()removeEventListener</code> ===
 
 
<syntaxhighlight lang="java">
 
<syntaxhighlight lang="java">
 
removeEventListener(type, handler);
 
removeEventListener(type, handler);
 
</syntaxhighlight>يزيل المعالج وذلك بتمرير الحدث من النوع <code>type</code> والمعالج (handler).
 
</syntaxhighlight>يزيل المعالج وذلك بتمرير الحدث من النوع <code>type</code> والمعالج (handler).
 +
 +
'''تنبيه''': هذا التابع مهمل، لذا استعمل التابع <code>remove()‎</code> مع اشتراك الحدث الذي أعاده التابع <code>addEventListener()‎</code>.
  
 
== الخاصيات ==
 
== الخاصيات ==
سطر 155: سطر 154:
 
* [https://facebook.github.io/react-native/docs/appstate صفحة AppState في توثيق React Native الرسميّ]
 
* [https://facebook.github.io/react-native/docs/appstate صفحة AppState في توثيق React Native الرسميّ]
 
[[تصنيف:ReactNative]]
 
[[تصنيف:ReactNative]]
 +
[[تصنيف:React Native API]]

المراجعة الحالية بتاريخ 14:12، 9 أكتوبر 2021

تُستخدم الواجهة البرمجيّة AppState لإخبار المستخدم بوجود التّطبيق في الواجهة الأماميّة (foreground)، أو الخلفية (background)، وإشعاره عند تغيّر ذلك.

تُستخدم AppState كثيرًا لتحديد نيّة الفعل (intent)، وتحضير ما يتوجّب فعله عند معالجة إشعارات الدّفع (push notifications).

حالات التطبيق

يكون التطبيق في إحدى الحالات التالية:

  • النّشطة active: يعمل التّطبيق في الواجهة الأماميّة.
  • في الخلفيّة background: يعمل التطبيق في الخلفية، وتعني أنّ المستخدم في إحدى الحالات التالية:
    • على تطبيقٍ آخر.
    • على الشّاشة الرئيسيّة (home screen).
    • (على منصّة Android) المستخدم على نشاط activity آخر (حتى لو أُطلِق من تطبيق المستخدم).
  • حالة الخمول inactive (على منصّة iOS): تحصل هذه الحالة عند الانتقال بين الواجهة الأماميّة والخلفيّة، وخلال فترة الخمول، مثل: الدّخول في العرض متعدّد المهام (Multitasking)، أو عند حدوث اتصالٍ وارد.

ويمكن الإطّلاع على توثيق شركة Apple لمزيدٍ من المعلومات.

الاستخدام الأساسي

يمكن معرفة الحالة الحاليّة من خلال تفحّص الخاصيّة AppState.currentState، والتي تُحدَّث دائمًا، وتكون قيمتها null عند بداية التشغيل ثم تستعيدها AppState عبر الجسر.

import React, { useRef, useState, useEffect } from "react";
import { AppState, StyleSheet, Text, View } from "react-native";

const AppStateExample = () => {
  const appState = useRef(AppState.currentState);
  const [appStateVisible, setAppStateVisible] = useState(appState.current);

  useEffect(() => {
    const subscription = AppState.addEventListener("change", nextAppState => {
      if (
        appState.current.match(/inactive|background/) &&
        nextAppState === "active"
      ) {
        console.log("App has come to the foreground!");
      }

      appState.current = nextAppState;
      setAppStateVisible(appState.current);
      console.log("AppState", appState.current);
    });

    return () => {
      subscription.remove();
    };
  }, []);

  return (
    <View style={styles.container}>
      <Text>Current state is: {appStateVisible}</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center",
  },
});

export default AppStateExample;
import React, { Component } from "react";
import { AppState, StyleSheet, Text, View } from "react-native";

class AppStateExample extends Component {
  state = {
    appState: AppState.currentState
  };

  componentDidMount() {
    this.appStateSubscription = AppState.addEventListener(
      "change",
      nextAppState => {
        if (
          this.state.appState.match(/inactive|background/) &&
          nextAppState === "active"
        ) {
          console.log("App has come to the foreground!");
        }
        this.setState({ appState: nextAppState });
      }
    );
  }

  componentWillUnmount() {
    this.appStateSubscription.remove();
  }

  render() {
    return (
      <View style={styles.container}>
        <Text>Current state is: {this.state.appState}</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center",
    alignItems: "center"
  }
});

export default AppStateExample;

عند عدم الرغبة برؤية انتقال AppState من الحالة active إلى الحالة inactive على منصة iOS يمكن إزالة متغير الحالة واستخدام القيمة appState.current.

يُظهر المثال السابق دائمًا الإشعار "Current state is: active" فقط، لأنّ التّطبيق يكون مرئيًّا للمستخدم عندما يكون في الحالة الفعّالة فقط؛ أمّا الحالة null فتحدث لحظيًّا فقط، لذا يُنصح بتجريب المثال على الجهاز الشّخصي بدلًا من المعاينة المضمنة (embedded preview).

الأحداث

change

يُطلَق هذا الحدث عند تغيّر حالة التّطبيق، ويستدعى المُنصت (listener) مع أحد قيم حالات التطبيق الحاليّة (التي ذكرناها في الأعلى).

memoryWarning

يُستخدم هذا الحدث عند الحاجة لإلقاء تحذير الذّاكرة أو إطلاقه.

focus

(يعمل على منصّة Android فقط) ويُطلَق عند تفاعل المستخدم مع التطبيق.

blur

(يعمل على منصّة Android فقط) ويُطلَق عند عدم تفاعل المستخدم مع التّطبيق، وهو مفيد عندما يسدل المستخدم ستار الإشعارات notification drawer، ولا تتغيّر AppState لكن يُطلق الحدث blur.

التوابع

‎addEventListener()‎

addEventListener(type, handler);

يضيف معالجًا لتغيرات AppState وذلك بالتنصّت للحدث من النوع change وربطه مع المعالج (handler).

‎removeEventListener()‎

removeEventListener(type, handler);

يزيل المعالج وذلك بتمرير الحدث من النوع type والمعالج (handler).

تنبيه: هذا التابع مهمل، لذا استعمل التابع remove()‎ مع اشتراك الحدث الذي أعاده التابع addEventListener()‎.

الخاصيات

currentState

AppState.currentState;

مصادر