在我的SSHsocket类中(不扩展或实现任何东西)我实例化HandlerThread:
socketHandlerThread = new HandlerThread(sessionTag);
socketHandlerThread.start();
然后我调用connect()方法:
socketHandler = new Handler(socketHandlerThread.getLooper()) {
public void handleMessage(Message msg) {
switch (msg.what) {
case TerminalService.SERVICE_TO_SOCKET_DO_CONNECT:
try {
connect();
} catch (IOException e) {
Message statusMsg = Message.obtain(null,SOCKET_TO_SERVICE_STATUS_DEAD, sessionDetailData.getUuid());
serviceHandler.sendMessage(statusMsg);
Log.e("SSH Socket id:" + sessionDetailData.getUuid() + " fails. ", e.toString());
}
break;
在connect()方法中,我需要打开yes / no对话框:
final String titleMessage = "Do you want to accept the hostkey (type " + algo + ") from " + host + " ?\n";
mainActivity.runOnUiThread(new Runnable() {
public void run() {
FragmentTransaction fragmentTransaction=mainActivity.getFragmentManager().beginTransaction();
AcceptKeyDialog acceptKeyDialog = new AcceptKeyDialog();
acceptKeyDialog.show(fragmentTransaction, "KEY_ACCEPT_DIALOG");
acceptKeyDialog.getTitleView().setText(titleMessage);
}
});
即使使用按钮,也会按预期填充对话框。但是在调试它时,runOnUiThread()内部(任何地方)的断点显示acceptKeyDialog片段实例的属性为null(膨胀视图,监听器......我称之为控制器等)。因此,显然调用AcceptKeyDialog的getTitleView()方法也会返回null。
public class AcceptKeyDialog extends DialogFragment {
private View keyDialogView;
//inner listener class for buttons
private AceeptKeyDialogFragmentController controller;
private TextView title;
private Button yesButton;
private Button noButton;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Window window = getDialog().getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
//DialogFragment.STYLE_NO_TITLE is not working as it should
window.requestFeature(Window.FEATURE_NO_TITLE);
controller = new AceeptKeyDialogFragmentController();
keyDialogView = inflater.inflate(R.layout.accept_key_dialog, container, false);
title = (TextView) keyDialogView.findViewById(R.id.accept_key_title);
yesButton = (Button) keyDialogView.findViewById(R.id.accept_key_yes_button);
noButton = (Button) keyDialogView.findViewById(R.id.accept_key_no_button);
title.setTextColor(Color.GREEN);
yesButton.setOnClickListener(controller);
noButton.setOnClickListener(controller);
return keyDialogView;
}
public TextView getTitleView(){
return title;
}
private class AceeptKeyDialogFragmentController implements View.OnClickListener {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.accept_key_yes_button:
break;
case R.id.accept_key_no_button:
break;
}
}
}
我认为这可能比使用处理程序消息(或handler.post ..或通过在消息中传递runnable)更好,但显然我错过了HandlerThread概念中的一些基本内容。我还认为它可能与传递的mainActivity引用有关,它由mainActivity=(MainActivity)msg.obj
但我没有看到活动状态被更改(监控MainActivity onStop()方法)
@Override
protected void onStop(){
Log.e("MainActivity is in onStop state","");
super.onStop();
}
最终目标是将用户决策传递回工作线程,并根据响应继续。你能建议吗?
答案 0 :(得分:0)
我在这个问题上获得了Tumbleweed徽章,所以它值得一个答案:) 然而,答案可能有点令人失望,因为我不完全了解它。我所描述的似乎是与主线程对象相关的一般问题,其中运行mainActivity.runOnUiThread()方法的另一个线程内的后向可见性。您可以在下面看到我没有实例化对话框对象。相反,我在主线程方法activity.fireInteractiveDialog(args)中运行,它为我做了这个 所以我不得不停止线程以获取用户输入,然后等待一个条件(以及输入本身)使线程再次运行。这一切都是由#34;守卫锁"编程构造,当然还有HandlerThread()的实例是传递条件状态的线程,并通知已停止的线程再次运行。 这是代码:
public synchronized void getUserInput() {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
Bundle args = new Bundle();
args.putString("somethingDialogTag", tag);
args.putString("somethingDialogTitle", title);
args.putStringArray("somethingDialogContent", content);
args.putBoolean("somethingDialogPassword", isPassword);
if (isPassword) {
args.putString("somethingDialogExistingPassword", sessionDetailData.getPassword());
}
//lets open the dialog
activity.fireInteractiveDialog(args);
}
});
while (!isInputAvailable) {
try {
Log.d("Thread " + String.valueOf(Thread.currentThread().getId()), " going to wait.");
wait();
Log.d("Thread " + String.valueOf(Thread.currentThread().getId()), " has woke up.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在同一个类中,HandlerThread更改(由Message对象携带)变量isInputAvailable以及准备好后提供的用户输入。
socketHandlerThread = new HandlerThread(tag);
socketHandlerThread.start();
socketHandler = new Handler(socketHandlerThread.getLooper()) {
public void handleMessage(Message msg) {
switch (msg.what) {
case Bus.SERVICE_TO_SOCKET_STATUS_KEY_ACCEPTANCE:
isKeyAccepted = ((MessageHolder) msg.obj).getLogic();
synchronized (advancedVerifier) {
advancedVerifier.notifyAll();
}
Log.e(tag + "User decided to accept key", String.valueOf(((MessageHolder) msg.obj).getLogic()));
break;
我希望有一天能帮助别人。如果有人理解跨线程(Android主线程和工作者)的对象可见性,那将会很棒。