Android:在单独的线程中获取输入时,Wait()主线程的 Dialog。

4
我正在编写一个Android活动,用户可以修改SQL数据库。该UI包括一个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(); 
    }   
}
3个回答

10

不要阻塞UI线程。系统将会提示"应用无响应"的错误。同时,也不要在非UI线程中尝试与用户交互。

当用户点击 "编辑" 时,不要直接启动编辑方法。只需弹出对话框收集所需信息,并在确认按钮上添加DialogInterface.OnClickListener,在此处调用编辑方法(因为现在已有所需信息)。

有关更多信息,请参见指南主题Dialogs


2
首先,您不应暂停主线程,因为这样会导致一切都被冻结,从用户的角度来看,这一点并不好。
其次,您应该弹出一个带有2个按钮(完成、取消)的对话框,并允许用户通过按下其中一个按钮来进一步操作。在此处,您可以了解如何显示自定义对话框:http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application Android多线程编程的第一条规则是,您不应该停止UI线程,所有长时间运行的操作都应该在单独的线程中进行。而所谓的长时间运行的操作包括SQLite数据库的写入/读取等操作。

1

在调用 wait 之前需要像这样获取对象锁:

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

但是为什么你想让主线程等待呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接