从 IntentHandler 传递什么上下文到需要它的方法?
What context to pass from an IntentHandler to a method that needs one?
我刚刚添加了一个新条件检查,该条件可能出现在使用 "borrowed" 代码显示消息的长时间运行的应用程序中。
语句在 IntentHandler
for class DbQuery
里面,其中 extends IntentService
:
showMessage(getApplicationContext(), "title", "note", mDatabase); // LINE 576 ****
showMessage
在 class Utilities
中定义并且一直有效,直到我决定看到它在我的 Android 4 平板电脑 (19) 上有效:
public static void showMessage(Context mContext, String tit, String mm, SQLiteDatabase m)
{
TextView message = new TextView(mContext);
TextView title = new TextView(mContext);
title.setText(tit);
message.setText(mm);
showCenteredInfoDialog(mContext, title, message, Gravity.CENTER, m); // **** LINE 505
}
调用异常发生的方法(标有*****):
public static void showCenteredInfoDialog
(
Context context, TextView message, TextView title, int
gravity, SQLiteDatabase m
)
{
context.getSystemService(Context.LAYOUTINFLATERSERVICE);
int YELLOWFOREGROUND ;
int BRIGHTBLUEBACKGROUND ;
{
YELLOWFOREGROUND = context.getResources().getColor(R.color.yellowforeground, null);
BRIGHTBLUEBACKGROUND =
context.getResources().getColor(R.color.brightbluebackground, null);
title.setTextColor(YELLOWFOREGROUND);
title.setBackgroundColor(BRIGHTBLUEBACKGROUND);
title.setGravity(Gravity.CENTER);
AlertDialog.Builder
builder = new AlertDialog.Builder(context);
builder.setPositiveButton("OK", null);
builder.setCustomTitle(title);
builder.setMessage(message.getText());
AlertDialog
dialog;
dialog = builder.show(); // *************************** LINE 482
dialog.setCanceledOnTouchOutside(false);
TextView
messageView = /*(TextView)*/ dialog.findViewById(android.R.id.message);
messageView.setTextColor(YELLOWFOREGROUND);
messageView.setBackgroundColor(BRIGHTBLUEBACKGROUND);
messageView.setTypeface(Typeface.MONOSPACE);
messageView.setGravity(gravity);
}
}
从 MainActivity
调用 showMessage
,其中传递的 Context
是 this
。
我想我不应该尝试从我的 IntentHandler
调用 showMessage
,但我想知道我应该如何调用它。
即,我应该传递什么 Context
?
对于 showMessage
的第一个参数,我尝试了 this
、getApplicationContext()
、getApplication()
、getApplication().getApplicationContext()
和 getBaseContext()
.都是return下面的错误。我什至提供了一个监听器而不是 null
作为 builder.setPositiveButton 的第二个参数。同样的错误:
E: FATAL EXCEPTION: IntentService[QueryDb]
Process: com.dslomer64.sqhell, PID: 24814
android.view.WindowManager$BadTokenException: Unable to add window --
token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:571)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:319)
at android.app.AlertDialog$Builder.show(AlertDialog.java:1112)
at com.dslomer64.sqhell.Utilities.showCenteredInfoDialog(Utilities.java:482)
at com.dslomer64.sqhell.Utilities.showMessage(Utilities.java:505)
at com.dslomer64.sqhell.QueryDb.onHandleIntent(QueryDb.java:576)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
E: getSlotFromBufferLocked: unknown buffer: 0xb40fe560
下面是部分调试跟踪的打印屏幕。
您应该为这个错误使用 activity 上下文,我希望能解决这个错误。
私有Context上下文
像这样在 onCreate 方法中初始化此上下文
上下文=这个; // 并使用这个上下文
showMessage(context, "title", "note", mDatabase);
并且还在单例中创建一个上下文类型变量class用作全局变量
一般来说,Android Service
可能是 运行 周围没有活动的时候。它只是 Android 中的另一个核心实体,如 Activity
或 BroadcastReceiver
。
如果您的 Android Service
不负责更新 UI 而是向您的 Activity
发送足够的数据以用于更新 UI。例如,您的 Android Service
可以使用 Broadcast
发送消息,而 Activity
可以通过 BroadcastReceiver
.
收听这些消息
在您的 Service
中定义 BROADCAST_FILTER
以便 BroadcastReceiver
可以识别消息意图来自服务:
public static String BROADCAST_FILTER = <Your service class>.class.getName();
从您的 Service
:
发送意向
//send a broadcast intent from your service
Intent intent = new Intent();
intent.setAction(BROADCAST_FILTER);
intent.putExtra("message", "<your message here>")
sendBroadcast(intent);
在您的 Activity
:
中注册 BroadcastReceiver
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra();
Utils.showMessage(<your activity>.this, ...);
//do your update here
}
};
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
//make sure your onReceive receives only the messages with this action
filter.addAction(<Your Service>.BROADCAST_FILTER);
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
由于我的应用程序的性质,在问我的问题之前我已经准备好 BroadcastManager
和 BroadcastReceiver
,所以我已经尝试了自己的弱尝试,类似于@user805311 的建议。
我说我不应该在 IntentService
中尝试 showMessage
基本上是正确的,尽管 @nishant 的 link 展示了如何做到这一点。
我对现有代码所做的更改如下:
在 IntentService
for QueryDb
中的 publishProgress
中,我在顶部的 if
中添加了代码以传递消息(存储在 progress
) 通过另一个 Intent
而不是 showMessage
,这导致异常,并立即开始通过 onPostExecute
关闭进程:
public class QueryDb extends IntentService
{
...
private void publishProgress(String progress)
{
Intent intent = new Intent(MatchesActivity.SOME_ACTION);
if(progress.toLowerCase().startsWith("Revise"))
{
intent.putExtra(MatchesActivity.STRING_EXTRA_NAME, progress);
onPostExecute();
}
else ...
...
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
在执行过程中这样调用是没有结果的:
String messageText = "Revise code!";
publishProgress(messageText);
已发布的消息文本在 MatchesActivity
中这样解释,它已启动 IntentService
并开始侦听消息。
这是第一个地方showMessage
终于成功了。
public class MatchesActivity extends Activity implements QueryDb.DbProcListenerForQueryDb
{
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
@Override public void onReceive(Context context, Intent intent)
{
String s = intent.getStringExtra(STRING_EXTRA_NAME) ;
if(s.startsWith("Revise"))
{
showMessage(_context, "Oh, no...", s, null);
MatchesActivity.this.setResult(RESULT_CANCELED);
}
else ...
...
}; // BroadcastReceiver
但是为了以可接受的 Context
继续我对 showMessage
的探索,我从上面的代码中删除了 showMessage
并在 onActivityResult
中添加了一个 MainActivity
,它也在 onActivityResult
中工作,其中收到并处理了关于取消的 "bad news":
public class MainActivity extends Activity
{
...
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intentData)
{
if(resultCode != RESULT_OK)
{
showMessage(this, "Bad news", "Only Scrabble", mDatabase);
return;
}
...
长话短说,将 showMessage
从 QueryDb
移动到 MatchesActivity
或 MainActivity
消除了错误Context
.
我刚刚添加了一个新条件检查,该条件可能出现在使用 "borrowed" 代码显示消息的长时间运行的应用程序中。
语句在 IntentHandler
for class DbQuery
里面,其中 extends IntentService
:
showMessage(getApplicationContext(), "title", "note", mDatabase); // LINE 576 ****
showMessage
在 class Utilities
中定义并且一直有效,直到我决定看到它在我的 Android 4 平板电脑 (19) 上有效:
public static void showMessage(Context mContext, String tit, String mm, SQLiteDatabase m)
{
TextView message = new TextView(mContext);
TextView title = new TextView(mContext);
title.setText(tit);
message.setText(mm);
showCenteredInfoDialog(mContext, title, message, Gravity.CENTER, m); // **** LINE 505
}
调用异常发生的方法(标有*****):
public static void showCenteredInfoDialog
(
Context context, TextView message, TextView title, int
gravity, SQLiteDatabase m
)
{
context.getSystemService(Context.LAYOUTINFLATERSERVICE);
int YELLOWFOREGROUND ;
int BRIGHTBLUEBACKGROUND ;
{
YELLOWFOREGROUND = context.getResources().getColor(R.color.yellowforeground, null);
BRIGHTBLUEBACKGROUND =
context.getResources().getColor(R.color.brightbluebackground, null);
title.setTextColor(YELLOWFOREGROUND);
title.setBackgroundColor(BRIGHTBLUEBACKGROUND);
title.setGravity(Gravity.CENTER);
AlertDialog.Builder
builder = new AlertDialog.Builder(context);
builder.setPositiveButton("OK", null);
builder.setCustomTitle(title);
builder.setMessage(message.getText());
AlertDialog
dialog;
dialog = builder.show(); // *************************** LINE 482
dialog.setCanceledOnTouchOutside(false);
TextView
messageView = /*(TextView)*/ dialog.findViewById(android.R.id.message);
messageView.setTextColor(YELLOWFOREGROUND);
messageView.setBackgroundColor(BRIGHTBLUEBACKGROUND);
messageView.setTypeface(Typeface.MONOSPACE);
messageView.setGravity(gravity);
}
}
从 MainActivity
调用 showMessage
,其中传递的 Context
是 this
。
我想我不应该尝试从我的 IntentHandler
调用 showMessage
,但我想知道我应该如何调用它。
即,我应该传递什么 Context
?
对于 showMessage
的第一个参数,我尝试了 this
、getApplicationContext()
、getApplication()
、getApplication().getApplicationContext()
和 getBaseContext()
.都是return下面的错误。我什至提供了一个监听器而不是 null
作为 builder.setPositiveButton 的第二个参数。同样的错误:
E: FATAL EXCEPTION: IntentService[QueryDb]
Process: com.dslomer64.sqhell, PID: 24814
android.view.WindowManager$BadTokenException: Unable to add window --
token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:571)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:310)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:319)
at android.app.AlertDialog$Builder.show(AlertDialog.java:1112)
at com.dslomer64.sqhell.Utilities.showCenteredInfoDialog(Utilities.java:482)
at com.dslomer64.sqhell.Utilities.showMessage(Utilities.java:505)
at com.dslomer64.sqhell.QueryDb.onHandleIntent(QueryDb.java:576)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:66)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
E: getSlotFromBufferLocked: unknown buffer: 0xb40fe560
下面是部分调试跟踪的打印屏幕。
您应该为这个错误使用 activity 上下文,我希望能解决这个错误。
私有Context上下文
像这样在 onCreate 方法中初始化此上下文
上下文=这个; // 并使用这个上下文
showMessage(context, "title", "note", mDatabase);
并且还在单例中创建一个上下文类型变量class用作全局变量
一般来说,Android Service
可能是 运行 周围没有活动的时候。它只是 Android 中的另一个核心实体,如 Activity
或 BroadcastReceiver
。
如果您的 Android Service
不负责更新 UI 而是向您的 Activity
发送足够的数据以用于更新 UI。例如,您的 Android Service
可以使用 Broadcast
发送消息,而 Activity
可以通过 BroadcastReceiver
.
在您的 Service
中定义 BROADCAST_FILTER
以便 BroadcastReceiver
可以识别消息意图来自服务:
public static String BROADCAST_FILTER = <Your service class>.class.getName();
从您的 Service
:
//send a broadcast intent from your service
Intent intent = new Intent();
intent.setAction(BROADCAST_FILTER);
intent.putExtra("message", "<your message here>")
sendBroadcast(intent);
在您的 Activity
:
BroadcastReceiver
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra();
Utils.showMessage(<your activity>.this, ...);
//do your update here
}
};
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
//make sure your onReceive receives only the messages with this action
filter.addAction(<Your Service>.BROADCAST_FILTER);
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
由于我的应用程序的性质,在问我的问题之前我已经准备好 BroadcastManager
和 BroadcastReceiver
,所以我已经尝试了自己的弱尝试,类似于@user805311 的建议。
我说我不应该在 IntentService
中尝试 showMessage
基本上是正确的,尽管 @nishant 的 link 展示了如何做到这一点。
我对现有代码所做的更改如下:
在 IntentService
for QueryDb
中的 publishProgress
中,我在顶部的 if
中添加了代码以传递消息(存储在 progress
) 通过另一个 Intent
而不是 showMessage
,这导致异常,并立即开始通过 onPostExecute
关闭进程:
public class QueryDb extends IntentService
{
...
private void publishProgress(String progress)
{
Intent intent = new Intent(MatchesActivity.SOME_ACTION);
if(progress.toLowerCase().startsWith("Revise"))
{
intent.putExtra(MatchesActivity.STRING_EXTRA_NAME, progress);
onPostExecute();
}
else ...
...
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
在执行过程中这样调用是没有结果的:
String messageText = "Revise code!";
publishProgress(messageText);
已发布的消息文本在 MatchesActivity
中这样解释,它已启动 IntentService
并开始侦听消息。
这是第一个地方showMessage
终于成功了。
public class MatchesActivity extends Activity implements QueryDb.DbProcListenerForQueryDb
{
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
{
@Override public void onReceive(Context context, Intent intent)
{
String s = intent.getStringExtra(STRING_EXTRA_NAME) ;
if(s.startsWith("Revise"))
{
showMessage(_context, "Oh, no...", s, null);
MatchesActivity.this.setResult(RESULT_CANCELED);
}
else ...
...
}; // BroadcastReceiver
但是为了以可接受的 Context
继续我对 showMessage
的探索,我从上面的代码中删除了 showMessage
并在 onActivityResult
中添加了一个 MainActivity
,它也在 onActivityResult
中工作,其中收到并处理了关于取消的 "bad news":
public class MainActivity extends Activity
{
...
@Override protected void onActivityResult(int requestCode, int resultCode, Intent intentData)
{
if(resultCode != RESULT_OK)
{
showMessage(this, "Bad news", "Only Scrabble", mDatabase);
return;
}
...
长话短说,将 showMessage
从 QueryDb
移动到 MatchesActivity
或 MainActivity
消除了错误Context
.