آموزشگاه برنامه نویسی تحلیل داده
آموزشگاه برنامه نویسی تحلیل داده

آموزش استفاده از Headless JSدر React Native

دوره های مرتبط با این مقاله

آموزش استفاده از Headless JSدر React Native

Headless JS روشی برای اجرای یک عملیات (در قالب Task) در JavaScript است، درحالی که application در پس زمینه اجرا می شود. برای مثال می توان از آن برای همگام سازی داده ها، مدیریت notification ها و پخش موسیقی استفاده کرد.

JS API

یک task، یک متد async است که آن را روی AppRegistry رجیستر می کنیم، مشابه رجیستر کردن application های React:


AppRegistry.registerHeadlessTask('SomeTaskName', () = >  require('SomeTaskName'));

سپس درون SomeTaskName.js:


module.exports = async (taskData) = >  {
  // do stuff
};

می توانید هرکاری درون task انجام دهید، مثلا درخواست های تحت شبکه، Timer و ...، تا زمانی که کاری با رابط کاربری نداشته باشید. هنگامی که task انجام شد (مثلا promise مقدار گرفت) react native به وضعیت "paused" می رود (مگر آنکه task های دیگری درحال اجرا باشند، یا یک application درحال اجرا باشد - نه در پس زمینه).

Java API

چند خط کد native برای این کار نیاز است. باید HeadlessJsTaskService را extend کنید، و متد getTaskConfig را override کنید:


public class MyTaskService extends HeadlessJsTaskService {
  @Override
  protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
    Bundle extras = intent.getExtras();
    if (extras != null) {
      return new HeadlessJsTaskConfig(
          "SomeTaskName",
          Arguments.fromBundle(extras),
          5000, // timeout for the task
          false // optional: defines whether or not  the task is allowed in foreground. Default is false
        );
    }
    return null;
  }
}

سپس Service را به فایل AndroidManifest.xml اضافه کنید:


< service android:name="com.example.MyTaskService" />

حال هربار که Service را start کنید، مثلا به شکل یک task زمان بندی شده یا در پاسخ به رویدادی سیستمی یا broadcast، JavaScript task را اجرا می کند و کنار می رود:

مثال ها:


Intent service = new Intent(getApplicationContext(), MyTaskService.class);
Bundle bundle = new Bundle();
bundle.putString("foo", "bar");
service.putExtras(bundle);
getApplicationContext().startService(service);

Retries (تلاش مجدد)

به طور پیش فرض، این task ها در صورت ناتمام ماندن، دوباره اجرا نمی شوند. برای اینکه درصورت ناتمام ماندن یک task، بار دیگر اجرا شود باید یک HeadlessJsRetryPolicy بسازید و یک خطای خاص throw کنید.

LinearCountingRetryPolicy یک پیاده سازی از HeadlessJsRetryPolicy است که به شما امکان می دهد ماکسیمم تعداد تلاش مجدد، با یک میزان تاخیر ثابت بین هر تلاش، را مشخص کنید. اگر این قابلیت برای هدف مورد نظرتان کافی نیست، می توانید HeadlessJsRetryPolicy خودتان را پیاده سازی کنید. این policy ها می توانند در قالب یک آرگومان اضافه به سازنده ی HeadlessJsTaskConfig ارسال شوند. مثلا:


HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy(
  3, // Max number of retry attempts
  1000 // Delay between each retry attempt
);
return new HeadlessJsTaskConfig(
  'SomeTaskName',
  Arguments.fromBundle(extras),
  5000,
  false,
  retryPolicy
);

این "تلاش مجدد" فقط زمانی اتفاق می افتد که خطای خاصی throw شود. درون یک task headless JS، می توانید این error را import کنید و هرزمان لازم دارید throw کنید.

مثلا:


import {HeadlessJsTaskError} from 'HeadlessJsTask';
module.exports = async (taskData) = >  {
  const condition = ...;
  if (!condition) {
    throw new HeadlessJsTaskError();
  }
};

اگر می خواهید به ازای همه ی error ها retry داشته باشید، باید آن ها را catch کنید و به ازی هر خطایی خودتان خطای بالا را throw کنید.

هشدارها

تابع ارسال شده به setTimeout همیشه آن طور که انتظار می رود رفتار نمی کند. این تابع زمانی فراخوانی می شود که application دوباره راه اندازی شود. اگر فقط به اندکی وقفه احتیاج دارید از قابلیت " retry" استفاده کنید.

به طور پیش فرض، اگر هنگامی که application درحال اجراست (نه در پس زمینه) بخواهید یک task اجرا کنید، application حین اجرا دچار خطا می شود. دلیل این امر آن است که مانع از آن شویم توسعه دهندگان با انجام کارهای سنگین در task، رابط کاربری را کند کنند. می توانید به عنوان چهارمین آرگومان از یک Boolean برای کنترل این رفتار استفاده کنید.

اگر service را از یک BroadcastReceiver شروع می کنید، حتما HeadlessJsTaskService.acquireWakeLockNow() را قبل از برگشت از onReceive() فراخوانی کنید.

مثال کاربردی

service ها می توانند از درون Java شروع شوند. این جا یک مثال ساده آورده ایم که به هرگونه تغییری در اتصال به اینترنت واکنش می دهد.

خطوط زیر قسمتی از فایل manifest در android را نشان می دهد که در آن گیرنده ی broadcast اصطلاحا register شده:


< receiver android:name=".NetworkChangeReceiver">
    < intent-filter>
         < action android:name="android.net.conn.CONNECTIVITY_CHANGE">
  < /intent-filter>
< /receiver>

گیرنده ی broadcast، intent را که به متد onReceive ارسال شده مدیریت می کند. این جا موقعیت مناسبی برای چک کردن این مسئله است که application در پس زمینه اجرا می شود یا نه. اگر application در پس زمینه است می توانیم intent را بدون نیاز به اطلاعات یا اطلاعات اضافه bundle شده با putExtra، شروع کنیم. (فراموش نکنید bundle فقط می تواند مقادیر parcelable را مدیریت کند):


public class NetworkChangeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        /**
          This part will be called everytime network connection is changed
          e.g. Connected - >  Not Connected
        **/
        if (!isAppOnForeground((context))) {
            /**
              We will start our service and send extra info about
              network connections
            **/
            boolean hasInternet = isNetworkAvailable(context);
            Intent serviceIntent = new Intent(context, MyTaskService.class);
            serviceIntent.putExtra("hasInternet", hasInternet);
            context.startService(serviceIntent);
            HeadlessJsTaskService.acquireWakeLockNow(context);
        }
    }
    private boolean isAppOnForeground(Context context) {
        /**
          We need to check if app is in foreground otherwise the app will crash.
         http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not
        **/
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List< activitymanager.runningappprocessinfo> appProcesses =
        activityManager.getRunningAppProcesses();
        if (appProcesses == null) {
            return false;
        }
        final String packageName = context.getPackageName();
        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            if (appProcess.importance ==
            ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
             appProcess.processName.equals(packageName)) {
                return true;
            }
        }
        return false;
    }
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager cm = (ConnectivityManager)
        context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        return (netInfo != null && netInfo.isConnected());
    }
}

  • 525
  •    0
  • تاریخ ارسال :   1398/06/10

دانشجویان گرامی اگر این مطلب برای شما مفید بود لطفا ما را در GooglePlus محبوب کنید
رمز عبور: tahlildadeh.com یا www.tahlildadeh.com
ارسال دیدگاه نظرات کاربران
شماره موبایل دیدگاه
عنوان پست الکترونیک

ارسال

آموزشگاه برنامه نویسی تحلیل داده
آموزشگاه برنامه نویسی تحلیل داده

تمامی حقوق این سایت متعلق به آموزشگاه تحلیل داده می باشد .