当前位置: 首页 > 面试题库 >

Android:对话框在单独的线程中获取输入时,等待线程的主线程

柳墨一
2023-03-14
问题内容

我正在Android中编写一个活动,用户可以在其中修改SQL数据库。用户界面由一个EditText(用户在其中输入名称)和一个Seekbar(用户在其中输入用户的吸引力)组成。在下面有很多按钮:添加,编辑,查看,删除。

当用户单击“编辑”按钮时,将显示一个输入对话框,要求用户输入记录号。完成后,将加载该记录。

我遇到的问题是,将显示输入对话框,并且当用户输入记录号时,其余的编辑方法将继续进行,以便在用户输入完输入时-由于该功能已经存在,所以什么也没发生完成了。

为了解决此问题,我决定使用多线程(我没有太多使用经验)。当按下编辑按钮时,主UI线程被阻止(使用wait()-这是因为我不希望用户在输入记录ID时激活UI),并且输入对话框显示在单独的线程。

输入输入后,将通知线程,其余的编辑功能将继续。(下面的代码)。

问题是,当我在UI线程上调用wait函数时,收到一条错误消息:“对象在wait()之前未被线程锁定”。 如何锁定UI线程?

我知道通常不应该阻止UI线程,但是我认为在这种情况下还可以,因为我不希望它接受任何用户输入。

谢谢你的帮助。

public class Attractivometer extends Activity implements OnClickListener {

    private Button      buttonAddRecord,    buttonEditRecord,   buttonSaveChanges;
    private Button      buttonDeleteRecord, buttonViewRecord;
    private EditText    fieldName;
    private SeekBar     seekbarAttractiveness;
    private String      inputFromInputDialog=null;
    private Thread      inputThread;


    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.Attractivometer);

        buttonAddRecord         = (Button) findViewById(R.id.buttonAddRecord);
        buttonSaveChanges       = (Button) findViewById(R.id.buttonSaveChanges);
        buttonEditRecord        = (Button) findViewById(R.id.buttonEditRecord);
        buttonDeleteRecord      = (Button) findViewById(R.id.buttonDeleteRecord);
        buttonViewRecord        = (Button) findViewById(R.id.buttonViewRecord);

        fieldName               = (EditText) findViewById(R.id.fieldName);

        seekbarAttractiveness           = (SeekBar) findViewById(R.id.seekbarAttractiveness);

        buttonAddRecord.setOnClickListener(this);
        buttonSaveChanges.setOnClickListener(this);
        buttonEditRecord.setOnClickListener(this);
        buttonDeleteRecord.setOnClickListener(this);
        buttonViewRecord.setOnClickListener(this);
    }


    public void onClick(View clickedItem)
    {

        switch(clickedItem.getId())
        {
        case R.id.buttonAddRecord:
            //.....
            break;


        case R.id.buttonSaveChanges:
          //... 
            break;

        case R.id.buttonEditRecord:

            inputThread = new Thread(new Runnable(){

                public void run()
                {
                    showInputDialog("Enter Record ID", InputType.TYPE_CLASS_NUMBER);
                }

            });
            inputThread.start();


            try {
                Thread.currentThread().wait();
            } catch (InterruptedException e) {
                Log.e("Attractivometer","Main Thread interrupted while waiting");
                e.printStackTrace();
            }

            try {
                inputThread.join();
            } catch (InterruptedException e) {
                Log.e("Attractivometer","Input Thread interrupted while joining");
                e.printStackTrace();
            }

            int recordId = Integer.parseInt(inputFromInputDialog);
            if(recordId!=null)
            {
                AttractivometerSQLHandler AttractivometerDatabaseHandler = new AttractivometerSQLHandler(this);
                AttractivometerDatabaseHandler.openDatabase();
                String recordName = AttractivometerDatabaseHandler.getName(recordId);
                String recordAttractiveness = AttractivometerDatabaseHandler.getAttractiveness(recordId);

                if(recordName==null || recordAttractiveness==null )
                {
                    //no record found.
                    Toast.makeText(this, "No record with that ID found", Toast.LENGTH_SHORT).show();
                }else
                {
                    fieldName.setText(recordName);
                    seekbarAttractiveness.setProgress( Integer.parseInt(recordAttractiveness) );
                    recordIsOpen(true);
                }


                AttractivometerDatabaseHandler.closeDatabase();
            }else
                //No input.
            recordIsOpen(false);

            break;

        case R.id.buttonDeleteRecord:
            //...
            break;

        case R.id.buttonViewRecord:
            //....

        }
    }

    private void showInputDialog(String prompt, int inputType)
    {
        AlertDialog.Builder inputDialog = new AlertDialog.Builder(this);

        inputDialog.setTitle("Record No.");

        final EditText fieldInput = new EditText(this);
        fieldInput.setInputType(inputType);
        fieldInput.setHint(prompt);

        inputDialog.setView(fieldInput);
        inputDialog.setPositiveButton("OK", new DialogInterface.OnClickListener()
        {

            public void onClick(DialogInterface arg0, int arg1)
            {
                inputFromInputDialog = fieldInput.getText().toString();
                inputThread.notify();

            }
        });

        inputDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
        {

            public void onClick(DialogInterface arg0, int arg1)
            {
                inputFromInputDialog = null;
                inputThread.notify();
            }
        });

        inputDialog.show(); 
    }   
}

问题答案:

不不不!不要阻塞UI线程。系统将引发“应用程序无响应”错误。另外,请勿尝试通过非UI线程与用户进行交互。

当用户单击“编辑”时,请勿启动编辑方法。只需弹出一个对话框即可收集所需的信息。DialogInterface.OnClickListener在肯定的按钮上添加a
,然后(现在有了所需的信息)从那里开始编辑方法。

有关更多信息,请参见指南主题对话框。



 类似资料:
  • 问题内容: 我正在为我的ubuntu服务器(针对我的多客户端匿名聊天程序)实现一种简单的线程池机制,并且需要使我的工作线程进入睡眠状态,直到需要执行一项工作(以函数指针和参数的形式) 。 我当前的系统即将关闭。我(工人线程正在)问经理是否有工作可用,以及是否有5毫秒没有睡眠。如果存在,请将作业添加到工作队列中并运行该函数。糟糕的循环浪费。 什么我 喜欢 做的是做一个简单的事件性的系统。我正在考虑有

  • 问题内容: 在这里,我想每秒钟调用一次“ Log.d”和“ postInvalidate”。但是,当我从LogCat检查它时,似乎循环运行的速度比我希望的要快。为什么这个循环不等待1000ms? 以下是LogCat中的输出。因此,您可以看到它根本没有休眠1秒钟。我也使用了Thread.sleep(在您建议之后) 这是最新的代码。是布尔值,现在是事实。 输出是 问题答案: 您需要类的方法。 使发送此

  • 在下面的代码中,为什么主线程要等到子线程完成。 Driver.java ThreadRunner.java 调用“t.start()”后,在驱动程序类中,程序是否应该退出?我没有使用join,但主线程仍在等待,直到新旋转的“ThreadRunner”运行开始。这是因为在java中,主线程(由main方法启动)总是等待所有线程关闭吗?

  • 我如何启动两个线程,其中thread1首先执行,thread2在thread1结束时启动,而主方法线程可以在不锁定其他两个线程的情况下继续工作? 我尝试了join(),但是它需要从线程调用,线程必须等待另一个线程,没有办法执行类似thread2.join(thread1)的操作;因此,如果我在main()中调用join,我将有效地停止主线程的执行,而不仅仅是Thread2的执行。 #编辑:为什么我

  • 问题内容: 您认为获得线程工作结果的最佳方法是什么?想象一个执行一些计算的线程,您如何警告主程序计算完成? 您可以每隔X毫秒轮询某个称为“作业完成”的公共变量或其他方式,但是随后您将在结果可用时才收到结果……主代码将浪费时间等待它们。另一方面,如果使用较低的X,则轮询将浪费CPU太多次。 因此,您如何做才能知道线程或某些线程已经完成了工作? 抱歉,如果它看起来与此其他问题相似,我想这可能是 ebe

  • Java 8的promise实现,即CompletableFuture,提供了应用(…)和get()方法。 其中,在必要时等待promise完成,然后返回其结果。 现在假设我们使用(或)链接一些代码以在UI线程上运行(请参见stackoverflow.com/thenApply和thenApplyAsync之间的差异)。 如果我们在UI线程中调用,比如Java以某种方式处理这种情况,或者它会导致所