Я совершил глупую (задним числом) ошибку, не осознав, что не должен выполнять большую логику в BroadcastReceiver.onReceive, поскольку этот бит кода выполняется в потоке пользовательского интерфейса.
Сервисный код, который вызывает широковещательное сообщение, такой же, как в предыдущем посте:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public class TweetService extends IntentService { ... @Override protected void onHandleIntent(Intent intent) { StatusListener listener = new UserStreamListener() { // override a whole load of methods - removed for brevity public void onStatus(Status status) { String theTweet = status.getText(); Intent tweetMessage = new Intent(TweetTask.NEW_TWEET); tweetMessage.putExtra(android.content.Intent.EXTRA_TEXT, status.getText()); sendBroadcast(tweetMessage); } } }; // code to connect to the twitter streaming API } } |
Это тогда обрабатывается как BroadcastReceiver:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
public class MyActivity extends Activity { protected void onPause() { super .onPause(); if (dataUpdateReceiver != null ) unregisterReceiver(dataUpdateReceiver); } protected void onResume() { super .onResume(); if (dataUpdateReceiver == null ) dataUpdateReceiver = new DataUpdateReceiver(); IntentFilter intentFilter = new IntentFilter(TweetTask.NEW_TWEET); registerReceiver(dataUpdateReceiver, intentFilter); } private class DataUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(TweetTask.NEW_TWEET)) { String theTweet = intent.getStringExtra(TweetTask.NEW_TWEET); Matcher matcher = p.matcher(theTweet); int startIndex = - 1 ; int endIndex = - 1 ; while (matcher.find()) { startIndex = matcher.start(); endIndex = matcher.end(); } if (startIndex != - 1 && endIndex != - 1 ) { String resolvedUrl = resolveUrl(theTweet.substring(startIndex, endIndex)); saveToDatabase(resolvedUrl); updateUI(resolvedUrl); } } } } } |
В частности, строка ‘resolUrl’, вероятно, была единственной, вызывающей проблему, так как она делает сетевой вызов для разрешения URL-адресов от укороченных ссылок .
Чтобы остановить зависание экрана, мне просто нужно было переместить большую часть кода из BroadcastReceiver в TweetService:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public class TweetService extends IntentService { ... @Override protected void onHandleIntent(Intent intent) { StatusListener listener = new UserStreamListener() { // override a whole load of methods - removed for brevity public void onStatus(Status status) { String theTweet = status.getText(); Matcher matcher = p.matcher(theTweet); int startIndex = - 1 ; int endIndex = - 1 ; while (matcher.find()) { startIndex = matcher.start(); endIndex = matcher.end(); } if (startIndex != - 1 && endIndex != - 1 ) { String resolvedUrl = resolveUrl(theTweet.substring(startIndex, endIndex)); saveToDatabase(resolvedUrl); Intent tweetMessage = new Intent(TweetTask.NEW_TWEET); tweetMessage.putExtra(android.content.Intent.EXTRA_TEXT, resolvedUrl); sendBroadcast(tweetMessage); } } } }; // code to connect to the twitter streaming API } } |
И тогда код для BroadcastReceiver становится намного проще, что означает, что мы делаем меньше работы над потоком пользовательского интерфейса:
1
2
3
4
5
6
7
8
9
|
private class DataUpdateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(TweetTask.NEW_TWEET)) { String url = intent.getStringExtra(TweetTask.NEW_TWEET); updateUI(url); } } } |
И замораживание интерфейса прошло!
Ссылка: Изучение Android: замораживание пользовательского интерфейса с BroadcastReceiver от нашего партнера JCG Марка Нидхэма в блоге Марка Нидхэма .