【问题标题】:Method of DialogFragment instantiated in mainActivity.runOnUiThread method returns null but dialog is shown在 mainActivity.runOnUiThread 方法中实例化的 DialogFragment 方法返回 null 但显示对话框
【发布时间】:2015-01-19 05:05:44
【问题描述】:

在我的 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() 方法中,我需要打开一个是/否对话框:

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 片段实例的属性为空(膨胀的视图、侦听器......我称之为控制器等)。所以显然调用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)msg.obj 完成的 mainActivity 的传递引用有关

但我没有看到活动状态正在改变(监控 MainActivity onStop() 方法)

@Override
    protected void onStop(){
        Log.e("MainActivity is in onStop state","");
        super.onStop();
    }

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

【问题讨论】:

    标签: android


    【解决方案1】:

    我在这个问题上获得了 Tumbleweed 徽章,所以它值得回答 :) 然而,答案可能有点令人失望,因为我没有完全理解它。我所描述的似乎是与运行 mainActivity.runOnUiThread() 方法的另一个线程内的主线程对象向后可见性相关的一般问题。正如您在下面看到的,我没有实例化对话框对象。相反,我在主线程方法 activity.fireInteractiveDialog(args) 中运行,它为我执行此操作。
    所以我不得不停止线程以获取用户输入,然后等待一个条件(以及输入本身)使线程再次运行。这一切都是由“保护锁”编程结构完成的,当然 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 主线程和工作线程)的对象可见性做出响应,那就太好了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 2012-04-26
      • 2012-08-17
      • 2016-11-11
      • 2011-04-19
      相关资源
      最近更新 更多