كيف يمكنني تحديث المعلومات في نشاط Android من خدمة خلفية

StackOverflow https://stackoverflow.com/questions/2468874

سؤال

أحاول إنشاء تطبيق Android بسيط يحتوي على قائمة نشاط للمعلومات ، عندما يبدأ التطبيق ، أخطط لبدء خدمة سيتم حساب البيانات باستمرار (ستتغير) وأريد أن تكون قائمة Activity متزامنة مع البيانات التي تحسبها الخدمة لحياة التطبيق.

كيف يمكنني إعداد نشاطي للاستماع إلى الخدمة؟ هل هذه هي أفضل طريقة للتعامل مع هذه المشكلة؟

على سبيل المثال ، إذا كنت تتخيل قائمة أسعار الأسهم - سيتم تغيير البيانات بانتظام وتحتاج إلى أن تكون متزامنة مع خدمة (في حالتي) التي تحسب/جلب البيانات باستمرار.

شكرا لك مقدما

هل كانت مفيدة؟

المحلول

كيف يمكنني إعداد نشاطي للاستماع إلى الخدمة؟ هل هذه هي أفضل طريقة للتعامل مع هذه المشكلة؟

لديك ثلاثة خيارات رئيسية ، كما أراها:

  1. الاقتراع. ال Activity يسأل بشكل دوري Service للحصول على أحدث البيانات. IMHO ، هذا الخيار يمتص ، لكنه بالتأكيد ممكن.

  2. عمليات الاسترجاعات. لكل إجابة جاكس ، Activity يسجل كائن رد الاتصال ("Observer") مع Service. ال Service يستدعي طريقة على رد الاتصال عندما تتغير البيانات ، والتي بدورها تقوم بتحديث واجهة المستخدم. يمكنك رؤية مثال على استخدام ذلك مع Service هنا.

  3. إذاعة Intents. ال Service يبث Intent عبر sendBroadcast() على تغيير البيانات. ال Activity سجلات أ BroadcastReceiver استخدام registerReceiver(), ، وذلك BroadcastReceiver يتم إخطار البث الوارد. هذا يؤدي إلى Activity لتحميل أحدث البيانات من Service, ، أو ربما فقط للحصول على أحدث البيانات من الإضافات في البث Intent. يمكنك رؤية مثال على استخدام هذه التقنية مع أ Service هنا.

نصائح أخرى

هذا يبدو وكأنه مرشح جيد لنمط المراقب. في الأساس ، سيقوم نشاطك (المراقب) بتسجيل نفسه في خدمة الخلفية (يمكن ملاحظته) ويمكنك دفع البيانات أو سحبها من نشاطك. سيكون مراقبك في هذه الحالة هو نشاطك وسيتم ملاحظته هو خدمتك.

إذا لم تكن تعرف شيئًا عن أنماط التصميم ، فقم بشراء "أنماط التصميم الأولى" ، فمن السهل القراءة ومليئة بالمعلومات الرائعة.

ملاحظة: أنا أقرأها الآن.

أنا حقًا أتساءل حقًا لماذا لم يذكر أحد مقاربة بسيطة باستخدام EventBus بواسطة أي مكتبة. هذا بالطبع إذا كنت لا تستخدم RX. المفضل لدي هو EventBus من GreenRobot.https://github.com/greenrobot/eventbus

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

تحتاج إلى استخدام BindService () لربط النشاط بخدمة التشغيل والتواصل معها.

public class BindingActivity extends Activity {
YourService mService;
boolean mBound = false;

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

@Override
protected void onStart() {
    super.onStart();
    // Bind to Your Service
    Intent intent = new Intent(this, YourService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    // Unbind from the service
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
}

/** Called when a button is clicked (the button in the layout file attaches to
  * this method with the android:onClick attribute) */
public void onButtonClick(View v) {
    if (mBound) {
        // Call a method from your Service.
        // However, if this call were something that might hang, then this request should
        // occur in a separate thread to avoid slowing down the activity performance.
        int num = mService.getRandomNumber();
        Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
    }
}

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // We've bound to the running Service, cast the IBinder and get instance
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
    }
 };
}

وخدمتك مثل:

public class LocalService extends Service {
    // Binder given to clients
   private final IBinder mBinder = new LocalBinder();
   // Random number generator
   private final Random mGenerator = new Random();

/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
    LocalService getService() {
        // Return this instance of LocalService so clients can call public methods
        return LocalService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

/** method for clients */
public int getRandomNumber() {
  return mGenerator.nextInt(100);
  }
}

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

يمكنك استخدام نوع من ArrayAdapter للحصول على البيانات في ListView. يحتوي ArrayAdapter على طريقة تسمى adpater.notifyDataStchanged () في كل مرة تتصل فيها هذه الطريقة ، سيرى المحول أن البيانات المقابلة قد تغيرت ثم تخطر عرض القائمة بأنه يجب تحديثه في الاحتمال التالي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top