لا يعرض CompletExtView AutoCompleteTextView النتيجة حتى عند تحديث ArrayAdapter

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

سؤال

أحاول الحصول على إكمال تلقائي (ACTV) لعرض النتائج التي أحصل عليها من مورد شبكة. لقد قمت بتعيين عرض الانتهاء إلى 2 وأستطيع أن أرى أن الطلب يتم إطلاقه عند الدخول إلى الشخصيات.

النتيجة التي أحصل عليها هي الصحيح. لنقول إنني أكتب "CA" ، وأحصل على النتيجة "السيارة" كإكمال تلقائي. لدي وظيفة رد اتصال تتلقى النتيجة من Asynctask وتضع النتيجة في ArrayAdapter. ثم أتصل. showdropdown () على ACTV ويظهر منسدلة فارغة (نصف حجم عنصر عادي). ثم إذا أدخلت الحرف الأخير "R" ويعرض ACTV "السيارة" ، يتم عرض المنسدلة والنتيجة فجأة في القائمة.

يحدث الشيء نفسه إذا كنت قد أدخلت حرفين (والتي تُرجع نتيجة صالحة) ، وإزالة الحرف الأخير. عند إزالة الحرف ، يتم عرض "السيارة" كقيمة الإكمال التلقائي.

هل واجه أي شخص هذه المشكلة؟ يبدو أن المحول مليء بالنتيجة ، لكن النتيجة لا تظهر حتى الإجراء التالي الذي أقوم به. لقد حاولت أيضًا تشغيل .NotifyDatAstechanged () بعد أن أضفت النتيجة إلى المحول ، ولكن لا ينبغي أن تكون هناك حاجة إليها ، أو؟

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

المحلول

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

أعتقد أنك قد تكون مخطئًا بشأن الحاجة إلى Asynctask. يقوم كائن المرشح بالفعل بعمل شيء مشابه لـ Asynctask: performFiltering() يتم في موضوع خلفية ، و publishResults() يتم استدعاؤه من موضوع واجهة المستخدم ، بعد الانتهاء من الأداء (). حتى تتمكن من القيام بطلب الشبكة مباشرة في أداء الأداء () ، وتعيين النتائج في كائن FilterResults ، ولن تضطر إلى القلق بشأن أن يكون طلب الشبكة بطيئًا جدًا ويسبب مشاكل في واجهة المستخدم.

حل بديل ، وهو أكثر تعقيدًا قليلاً ، لكن ما أقوم به في كائن المرشح الخاص بي (نظرًا للهندسة المعمارية الحالية التي تقوم بمكالمات API في الخلفية ، باستخدام رد اتصال غير متزامن بدلاً من الخطوة الحظر/المتزامنة كما هو مطلوب للأداء ( ) ، هو استخدام كائن متزامن مع WAIT ()/etmify () للقيام بمراقبة المتقاطع ، وبالتالي فإن التأثير هو نفسه القيام بطلب الشبكة مباشرة في أداء الأداء () ، ولكنه يحدث بالفعل في مؤشرات ترابط متعددة:

// in Filter class..
protected FilterResults performFiltering(CharSequence constraint) {

    APIResult response = synchronizer.waitForAPI(constraint);
    // ...
}

// callback invoked after the API call finishes:
public void onAPIComplete(APIResult results) {
    synchronizer.notifyAPIDone(results);
}

private class Synchronizer {
    APIResult result;

    synchronized APIResult waitForAPI(CharSequence constraint) {
        someAPIObject.startAsyncNetworkRequest(constraint);
        // At this point, control returns here, and the network request is in-progress in a different thread.
        try {
            // wait() is a Java IPC technique that will block execution until another
            // thread calls the same object's notify() method.
            wait();
            // When we get here, we know that someone else has just called notify()
            // on this object, and therefore this.result should be set.
        } catch(InterruptedException e) { }
        return this.result;
    }

    synchronized void notifyAPIDone(APIResult result) {
        this.result = result;
        // API result is received on a different thread, via the API callback.
        // notify() will wake up the other calling thread, allowing it to continue
        // execution in the performFiltering() method, as usual.
        notify();
    }
}

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

نصائح أخرى

أعتقد أن إجابة جو هي الطريق للذهاب. ومع ذلك ، أعتقد أنك يجب أن تستخدم العد التنازلي بدلا من الانتظار/إخطار.

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

// in Filter class..
protected FilterResults performFiltering(CharSequence constraint) {
  APIResult response = synchronizer.waitForAPI(constraint);
  // ...
}

// callback invoked after the API call finishes:
public void onAPIComplete(APIResult results) {
  synchronizer.notifyAPIDone(results);
}

private class Synchronizer {
  APIResult result;
  CountDownLatch latch;

  synchronized APIResult waitForAPI(CharSequence constraint) {
      latch = new CountDownLatch(1);
      someAPIObject.startAsyncNetworkRequest(constraint);
      // At this point, control returns here, and the network request is in-progress in a different thread.
      try {
        // Will wait till the count is 0...
        // If the count is already 0, it'll return immediately. 
        latch.await();
        // When we get here, we know that someone else has just called notify()
        // on this object, and therefore this.result should be set.
    } catch(InterruptedException e) { }
    return this.result;
  }

  synchronized void notifyAPIDone(APIResult result) {
    this.result = result;
    // API result is received on a different thread, via the API callback.
    // countDown() will wake up the other calling thread, allowing it to continue
    // execution in the performFiltering() method, as usual.
    latch.countDown();
  }
}

أخيرًا ، ليس لدي رصيد كاف لنشر تعليق ، وإلا فسوف يكون لدي ...

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