2016-03-17 1 views
0

По-видимому, простое требование - обновить пользовательский интерфейс от IntentService. В приведенном ниже снимке, когда нажата кнопка Start Service, мне нужно показать ProgressBar выше TextView и после задержки удалить ProgressBar.Невозможно обновить пользовательский интерфейс от IntentService

AVD Screenshot

Найдено много ответов на SO, но почему-то не удалось еще взломать. Я понимаю от this, что LocalBroadcastManager - хороший способ пойти. Я также пробовал следовать за this (подход с Handler с), но он также не показывает ProgressBar. Наконец, на основании ответа this, вот что я получил. Выход, с которым я до сих пор справлялся, - это всего лишь Toast s, появляющийся последовательно, после того, как все протоколирование завершено.

Очень ценно, если бы вы могли указать, где я ошибаюсь, боролись довольно долгое время. Спасибо заранее!

MainActivity обновленный

public class MainActivity extends AppCompatActivity 
{ 
    private static final String TAG = "MainActivity"; 
    private ProgressBar pb; 
    private MyBroadcastReceiver myBroadcastReceiver; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     pb = (ProgressBar) findViewById(R.id.pb); 
     myBroadcastReceiver = new MyBroadcastReceiver(); 

     LocalBroadcastManager.getInstance(this).registerReceiver(myBroadcastReceiver, new IntentFilter("ACTION")); 
    } 

    private void updateUI(boolean show) 
    { 
     if (show) 
      pb.setVisibility(View.VISIBLE); 
     else 
      pb.setVisibility(View.GONE); 
//  Toast.makeText(this, "UI Updated...", Toast.LENGTH_LONG).show(); 
    } 

    public void startIt(View view) 
    { 
     Intent intent = new Intent(this, NanisIntentService.class); 
     startService(intent); 
    } 

    public class MyBroadcastReceiver extends BroadcastReceiver 
    { 
     @Override 
     public void onReceive(final Context context, Intent intent) 
     { 
      String action = intent.getAction(); 
      Log.e(TAG, "In onReceive(): " + action); 
      if (action.equals("ACTION")) 
      { 
       updateUI(true); 
      } // of if (action = "ACTION") 
      else if (action.equals("NOITCA")) 
      { 
       updateUI(false); 
      } // of else of if (action = "ACTION") 
     } // of onReceive() 
    } // of class MyBroadcastReceiver 
} 

IntentService обновленный

public class NanisIntentService extends IntentService 
{ 
    private static final String TAG = "NanisIntentService"; 

    public NanisIntentService() 
    { 
     super("NanisIntentService"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) 
    { 
     Log.e(TAG, "In onHandleIntent(): Intent is being serviced"); 
     LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION")); 
     int i = 0; 
     while (i <= 50) 
     { 
      try 
      { 
       Thread.sleep(50); 
       i++; 
       Log.e("", "" + i); 
      } catch (InterruptedException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 
     LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA")); 
     Log.e(TAG, "In onDestroy(): The service has been destroyed"); 
    } 
} 

    @Override 
    public void onStart(Intent intent, int startId) 
    { 
     super.onStart(intent, startId); 
     LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION")); 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 
     LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA")); 
     Log.e(TAG, "In onDestroy(): The service has been destroyed"); 
    } 
} 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 
     LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA")); 
     Log.e(TAG, "In onDestroy(): The service has been destroyed"); 
    } 
} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    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: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="testing.com.myintentservice.MainActivity"> 

    <ProgressBar 
     android:id="@+id/pb" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_above="@+id/tv" 
     android:layout_centerHorizontal="true" 
     android:indeterminate="true" 
     android:visibility="gone"/> 

    <TextView 
     android:id="@+id/tv" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerInParent="true" 
     android:text="Hello IntentService!" 
     android:textColor="#1298CE" 
     android:textSize="32sp"/> 

    <Button 
     android:id="@+id/bt" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     android:text="Start Service" 
     android:onClick="startIt"/> 
</RelativeLayout> 

AndroidManifest

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

       <category android:name="android.intent.category.LAUNCHER"/> 
      </intent-filter> 
     </activity> 
     <service android:name="testing.com.myintentservice.NanisIntentService"/> 
    </application> 

ответ

2

Во-первых, вы привязывания основной поток приложения в течение ~ 2,5 сек. Это заморозит ваш пользовательский интерфейс в течение этого периода времени. Не делайте этого.

Во-вторых, вы вызываете updateUI() раз до ~ 2,5 секунд и один раз после. Поскольку вы привязываете основной поток приложений за это время, это будет иметь тот же визуальный эффект, что и вызов updateUI() дважды подряд после задержки. updateUI() переключает видимость ProgressBar, поэтому два вызова отменяют друг друга, оставляя вас в том же состоянии, в котором вы начали.

Мне нужно показать ProgressBar над единственным TextView и после задержки удалить ProgressBar.

Показаны ProgressBar в течение 2,5 секунд, независимо от фактической выполняемой работы, довольно произвольно.

Это, как говорится, называют updateUI() один раз, а затем использовать pb.postDelayed(), чтобы запланировать Runnable запустить 2500 миллисекунд позже, когда run() метод в Runnable вызовов updateUI() во второй раз. Это позволяет вам блокировать основной поток приложений, поэтому он позволяет первому вызову updateUI() вступить в силу, сохраняя при этом 2,5-секундную продолжительность.

+0

Спасибо за быстрый ответ, @CommonsWare! Извините, но я пропустил упоминание о том, что это _experiment_, _PoC_ - поэтому вместо задержки в 2,5 секунды будет установлена ​​неопределенная загрузка в Интернете, в течение которой мне нужно показать «ProgressBar». Будет ли ваше предложение по-прежнему оставаться хорошим? Очень ценю, если бы вы любезно разработали решение немного по возможности. Ура! –

+1

@NarayanaJ: «Будут ли ваши предложения по-прежнему оставаться хорошими?» - считая, что продолжительность «ProgressBar» основана на сервисе, вы можете так же настроить вещи таким образом, чтобы начать. Используйте два разных события «LocalBroadcastManager» для «show» и «hide». В краткосрочной перспективе поставьте задержку в услуге в виде «поддельной работы», которую выполняет служба. Затем вы можете заменить фальшивую работу на реальную работу, и логика 'ProgressBar' не должна изменяться. – CommonsWare

+0

, пожалуйста, проверьте обновленный код в моем исходном вопросе. То, что я сделал, это: -Прислал «поддельную работу» на «IntentService» -Сделать 2 действия для широковещательной передачи, одну, чтобы показать, и одну, чтобы скрыть «ProgressBar» . Я также не уверен, что вызов «Runnable» что вы изначально предлагали) все равно должны быть сделаны, а также точно, как это должно быть сделано. «ProgressBar» по-прежнему не отображается. Пожалуйста, ответьте. –

0

Большое спасибо, @CommonsWare! Наконец он получил его на работу.Нужно было два приемника для двух разных действий , которые я обнаружил here.

В пользу тех, кто ищет для окончательного рабочего кода ...

экраны Результат: - после нажатия и после обработки

Pardon любые копипаст привидения в коде, это все-таки РоС, хотя и функциональный.

+0

Приведенные ссылки не работают. – user3705478

+0

@ user3705478, интересно, как оно исчезло из пасты. Будет обновлен этот пост с кодом, когда я получу свободное время. До этого, пожалуйста, несите. –

Смежные вопросы