2012-03-09 23 views
2

我在Android中编写用户修改SQL数据库的活动。用户界面由用户输入名称的EditText和用户输入人物吸引力的Seekbar组成。在下面有一堆按钮:添加,编辑,查看,删除。Android:等待()主线程,而对话框在单独的线程中输入时输入

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

我遇到的问题是输入对话框会显示出来,而当用户输入记录号时,编辑方法的其余部分会继续执行,这样当用户输入输入时 - 什么都不会发生,因为该功能已经完成。

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

输入完成后,会通知该线程,并继续执行编辑功能的其余部分。 (代码如下)。

问题是,当我在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(); 
    } 
} 

回答

6

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

当用户点击“编辑”时,不要启动编辑方法。只需弹出一个对话框来收集所需的信息。向正面按钮添加一个DialogInterface.OnClickListener,并且(现在需要的信息)从那里开始编辑方法。

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

+0

谢谢!我对使用对话框有错误的想法:) – 2012-03-09 09:21:33

1

调用之前需要等待获取对象锁是这样的:

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

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

1

首先,你不应该暂停主线程,因为如果你这样做,所有东西都会被冻结,从用户的角度来看,这并不是很好。

第二,您应该弹出一个带有2个按钮(完成,取消)的对话框,并允许用户按下其中一个按钮进一步。在这里,您可以了解如何显示自定义对话框:http://www.helloandroid.com/tutorials/how-display-custom-dialog-your-android-application

Android中多线程编程的首要规则是,您永远不应该停止UI线程,并且所有长时间运行的操作都应该在单独的线程中进行。通过长时间运行操作,我的意思是,SQLite数据库写/读等。