在mainActivity.runOnUiThread方法中实例化的DialogFragment方法返回null但是显示了对话框

时间:2015-01-01 18:01:32

标签: android

在我的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();
    }

最终目标是将用户决策传递回工作线程,并根据响应继续。你能建议吗?

1 个答案:

答案 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主线程和工作者)的对象可见性,那将会很棒。