Android SharedReferenceListener中的CalledFromErrorThreadException
我有一个IntentService,它会更新如下首选项:Android SharedReferenceListener中的CalledFromErrorThreadException,android,sharedpreferences,Android,Sharedpreferences,我有一个IntentService,它会更新如下首选项: SharedPreferences.Editor editor = userPrefs.edit(); editor.putInt("COUNT", intCount); editor.commit(); 在我的主要活动中,我正在监听偏好更改并更新文本视图 userPrefsListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override p
SharedPreferences.Editor editor = userPrefs.edit();
editor.putInt("COUNT", intCount);
editor.commit();
在我的主要活动中,我正在监听偏好更改并更新文本视图
userPrefsListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("COUNT")) {
final TextView txvCounter = (TextView) findViewById(R.id.TXV_COUNTER);
if(txvCounter != null) {
SharedPreferences userPrefs = getSharedPreferences("USER_SCORE", 0);
int intCount = userPrefs.getInt("COUNT", 0);
txvFishcounter.setText(String.format("%03d",intCount));
}
}
}
};
userPrefs.registerOnSharedPreferenceChangeListener(userPrefsListener);
对于Android2.3,一切正常,但对于2.2,每次触发OnSharedListener时,都会调用FromErrorThreadException
谢谢你的帮助 运行
onSharedPreferenceChanged()
回调的线程不是2.2设备中的主UI线程,该设备提供了从错误线程异常调用的(因此违反了仅从UI线程调用UI toolkit的第二条规则)。让代码在UI线程上运行的一种简单方法是使用。只需将代码主体包装在一个新的可运行的:
activity.runOnUiThread(new Runnable() {
public void run() {
// Code which updates UI controls goes here.
}
});
可以找到关于2.2和2.3之间的更改的简短讨论以及发生更改的原因的代码片段。运行onSharedPreferenceChanged()
回调的线程不是2.2设备中的主UI线程,该设备提供了调用FromErrorThreadException
(因此违反了仅从UI线程调用UI toolkit的第二条规则)。获取要在UI线程上运行的代码的简单方法是使用。只需将代码体包装在新的可运行的:
activity.runOnUiThread(new Runnable() {
public void run() {
// Code which updates UI controls goes here.
}
});
可以找到关于2.2和2.3之间的更改的简短讨论,以及发生更改的原因的代码片段。之所以提出从错误线程异常调用,是因为不应该从IntentService
调用OnChangeListener
不过,您可以做的是发送一个广播(实际上您也可以包括该值)
如果您仅使用SharedReference
进行通信,您可以完全替换它(我建议这样做,因为SharedReference会浪费写入周期)
您可以使用如下代码发送广播:
/**
* Send an Intent with the Broadcast, a permission and a Bundle
*
* @param context
* A context to use
* @param broadcast
* String to use, eg. "de.bulling.smstalk.ENABLE"
* @param permission
* Permission needed for receiving
* @param bundle
* Extras to attach
*/
public static void send_broadcast(Context context, String broadcast, String permission, Bundle bundle) {
//SettingsClass.log_me(tag, "Sending broadcast " + broadcast);
Intent i = new Intent();
i.setAction(broadcast);
if (bundle != null) {
i.putExtras(bundle);
}
if (permission != null) {
context.sendBroadcast(i, permission);
} else {
context.sendBroadcast(i);
}
}
您还应该包括自定义权限,以便其他应用程序无法获得广播,但不一定需要
要接收广播,请在活动中注册一个接收器,例如
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle b = intent.getExtras();
doSomething();
}
};
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
IntentFilter filter = new IntentFilter();
filter.addAction(YOURBROADCAST);
registerReceiver(receiver, filter);
[...]
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
您也应该考虑使用<代码>汉德勒<代码> s,所以您在OnCuxEistInter调用中的方法是由MIUI线程运行的。
例如:
Handler mHandler = new Handler();
Runnable myCode = new Runnable(){
@Override
protected void onRun() {
yourCode();
}
};
mHandler.run(myCode);
这还具有使用runDelayed()运行代码delayed的优点
,因此您不必使用睡眠
,UI仍将响应。引发调用FromErrorThreadException
的原因是OnChangeListener
不应该从IntentService
调用
不过,您可以做的是发送一个广播(实际上您也可以包括该值)
如果您仅使用SharedReference
进行通信,您可以完全替换它(我建议这样做,因为SharedReference会浪费写入周期)
您可以使用如下代码发送广播:
/**
* Send an Intent with the Broadcast, a permission and a Bundle
*
* @param context
* A context to use
* @param broadcast
* String to use, eg. "de.bulling.smstalk.ENABLE"
* @param permission
* Permission needed for receiving
* @param bundle
* Extras to attach
*/
public static void send_broadcast(Context context, String broadcast, String permission, Bundle bundle) {
//SettingsClass.log_me(tag, "Sending broadcast " + broadcast);
Intent i = new Intent();
i.setAction(broadcast);
if (bundle != null) {
i.putExtras(bundle);
}
if (permission != null) {
context.sendBroadcast(i, permission);
} else {
context.sendBroadcast(i);
}
}
您还应该包括自定义权限,以便其他应用程序无法获得广播,但不一定需要
要接收广播,请在活动中注册一个接收器,例如
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle b = intent.getExtras();
doSomething();
}
};
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
IntentFilter filter = new IntentFilter();
filter.addAction(YOURBROADCAST);
registerReceiver(receiver, filter);
[...]
}
@Override
public void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
您也应该考虑使用<代码>汉德勒<代码> s,所以您在OnCuxEistInter调用中的方法是由MIUI线程运行的。
例如:
Handler mHandler = new Handler();
Runnable myCode = new Runnable(){
@Override
protected void onRun() {
yourCode();
}
};
mHandler.run(myCode);
这还具有使用runDelayed()
运行代码延迟的优点,因此您不必使用sleep
,UI仍将响应。此回调将在主线程上运行。
,因此可以尝试打印线程名thread.currentThread().getName()
,如果不是主线程,则可能是原因。此回调将在主线程上运行。
,因此可以尝试打印线程名thread.currentThread().getName()
,如果不是主线程,则可能是原因。