在本文中,您将会了解到关于Android:对话框在单独的线程中获取输入时,等待线程的主线程的新资讯,同时我们还将为您解释android四种对话框的相关在本文中,我们将带你探索Android:对话框在单
在本文中,您将会了解到关于Android:对话框在单独的线程中获取输入时,等待线程的主线程的新资讯,同时我们还将为您解释android四种对话框的相关在本文中,我们将带你探索Android:对话框在单独的线程中获取输入时,等待线程的主线程的奥秘,分析android四种对话框的特点,并给出一些关于Android .aidl中的单向声明是否可以保证在单独的线程中调用该方法?、android – MediaPlayer应该在单独的线程中运行吗?、android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?、android – 获取主线程的消息队列和处理程序的实用技巧。
本文目录一览:- Android:对话框在单独的线程中获取输入时,等待线程的主线程(android四种对话框)
- Android .aidl中的单向声明是否可以保证在单独的线程中调用该方法?
- android – MediaPlayer应该在单独的线程中运行吗?
- android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?
- android – 获取主线程的消息队列和处理程序
Android:对话框在单独的线程中获取输入时,等待线程的主线程(android四种对话框)
我正在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(); } }
答案1
小编典典不不不!不要阻塞UI线程。系统将引发“应用程序无响应”错误。另外,请勿尝试通过非UI线程与用户进行交互。
当用户单击“编辑”时,请勿启动编辑方法。只需弹出一个对话框即可收集所需的信息。DialogInterface.OnClickListener
在肯定的按钮上添加a
,然后(现在有了所需的信息)从那里开始编辑方法。
有关更多信息,请参见指南主题对话框。
Android .aidl中的单向声明是否可以保证在单独的线程中调用该方法?
我正在为Android手机的客户端/服务器应用程序设计框架。我对Java和Android都相当陌生(但对于一般的编程(尤其是线程编程)不是新的)。
有时,我的服务器和客户端将处于同一进程中,有时它们将处于不同的进程中,具体取决于确切的用例。客户端和服务器接口如下所示:
IServer.aidl:
package com.my.application;interface IServer { /** * Register client callback object */ void registerCallback( in IClient callbackObject ); /** * Do something and report back */ void doSomething( in String what ); . . .}
IClient.aidl:
package com.my.application;oneway interface IClient { /** * Receive an answer */ void reportBack( in String answer ); . . .}
现在,这里变得有趣了。我可以预见一些用例,在这些用例中,客户端调用IServer.doSomething()
又需要IClient.reportBack()
根据所报告的内容IClient.reportBack()
再次调用IClient.doSomething()
。
这里的问题是,IServer.doSomething()
通常不会重入。没关系,只要IClient.reportBack()
总是在新线程中调用它即可。在这种情况下,我可以确保的实现IServer.doSomething()
总是synchronized
适当的,以便从新线程进行的调用一直阻塞到第一个调用返回为止。
如果一切都按我认为的方式工作,那么通过将IClient接口声明为oneway
,我保证情况确实如此。至少,我想不出什么办法,从呼叫IServer.doSomething()
到IClient.reportBack()
可以立即返回(什么oneway
是应该保证),但IClient.reportBack
仍然能够重新调用IServer.doSomething
在同一个线程递归。必须启动IServer中的新线程,或者可以将旧的IServer线程重新用于IServer.doSomething()的内部调用,但前提是IServer.doSomething()
必须返回外部调用。
所以我的问题是,一切都按我认为的方式工作吗?Android文档几乎没有提及oneway
接口。
答案1
小编典典oneway关键字表示,如果该呼叫导致IPC(即,呼叫者和被呼叫者位于不同的进程中),则呼叫进程将不等待被呼叫进程处理IPC。如果未生成IPC(即它们都在同一进程中),则该调用将是同步的。这是一个不幸的细节,大大简化了活页夹IPC的实现。如果它们处于同一进程中,则该调用只是常规的Java方法调用。
android – MediaPlayer应该在单独的线程中运行吗?
我的代码是基于这个例子:http://developer.android.com/guide/topics/media/mediaplayer.html
在该示例中,除了prepareAsync()调用之外,没有任何内容是线程.令我困惑的是,当我阅读关于Service类的时候,我发现这个信息:
“注意:一个服务在其主机进程的主线程中运行 – 该服务不会创建自己的线程,并且不会在单独的进程中运行(除非另有指定),这意味着如果您的服务将执行任何cpu密集型工作或阻塞操作(如MP3播放或网络连接)时,您应该在服务中创建一个新的线程来完成此工作,通过使用单独的线程可以降低应用程序无响应(ANR)错误的风险,应用程序的主线程可以保持专用于与您的活动的用户交互.
我问的原因是应用程序有时候(通常当断开连接时)在流式传输音频时冻结UI.我完全明白,由于活动和服务运行在同一个线程上,因此服务使cpu变得更加强大,UI会冻结.但是,我应该期望MediaPlayer是如此激烈?那就是应该在单独的线程上运行吗?
解决方法
android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?
@Override protected void onPause (){ super.onPause(); // ...prepare myTransactionValues // This Could be anything like insert,bulkInsert,query,delete,etc. getContentResolver().insert(CONTENT_URI,myTransactionValues) }
但是,看起来这个数据库操作正在主线程上完成.工作是在幕后的一个单独的线程中完成的吗?它应该在它自己的线程中吗?如果应该,是否有推荐的方式(也许是服务)?
解决方法
android – 获取主线程的消息队列和处理程序
解决方法
我有类似的需求.我想知道MessageQueue什么时候是空的,当我发布一些东西时,我想知道什么时候它变空了,什么都没做.我查看了MessageQueue.IdleHandler,发现它没有像我想要的那样表现我提出了另一个解决方案.
在我的情况下,我想使用Looper / Handler机制来顺序执行文件下载.基本上我想要执行的每个下载都包含在Runnable中.我只希望一次运行一个,所以这种模式运行良好,而不必深入研究更复杂的线程解决方案的细节.另外,我想知道什么时候我第一次把东西放进队列并开始工作,并想知道什么时候完成(队列是空的).
我能够使用处理程序的消息机制来实现这一点.消息按Runnables顺序处理,因此您可以策略性地将消息放入队列中,以帮助您了解队列的状况.与Handler队列中的Runnables不同,对于最终提供解决方案的消息,存在一些查询和删除功能.
我所做的是每次向Handler添加一个runnable(通过Handler.post),我还会删除自定义QUEUE_EMPTY消息的所有实例,然后添加一个新的QUEUE_EMPTY消息.这可确保我在队列末尾有一条QUEUE_EMPTY消息.一旦我在我的子类处理程序中遇到QUEUE_EMPTY消息,我知道我在队列的末尾.另外,如果我在添加runnable时没有在队列中找到QUEUE_EMPTY消息,我知道队列是空的并且线程处于空闲状态.
正如一些人会很快指出的那样,这种解决方案存在一些真正的低效率.如果队列中有大量条目,则必须遍历队列以获取这些“标记”消息可能是一个真正的性能问题.就我而言,我一次只处理少量文件下载,因此任何性能损失都可以忽略不计.如果你有类似的情况,我认为这是一个非常合理的解决方案. Android SDK为MessageQueue提供这些基本功能本来不错.我同意理想的是你不想弄乱MessageQueue,但知道它何时处于空闲/工作/空状态似乎是合理的事情,而且我确信当有价值知道这些事情时会有很多场景.
class DownloaderThread extends Thread { private static final int QUEUE_EMPTY = 9999; private MyHandler handler; @Override public void run() { try { Looper.prepare(); handler = new MyHandler(); Looper.loop(); } catch (Throwable t) { Log.e(TAG,"halted due to an error",t); } } public void post(Runnable r) { if(!handler.hasMessages(QUEUE_EMPTY)) { Log.v(TAG,"Download queue was empty. First element being added."); } handler.post(r); handler.removeMessages(QUEUE_EMPTY); handler.sendEmptyMessage(QUEUE_EMPTY); } class MyHandler extends Handler { @Override public void handleMessage(Message msg) { if(msg.what == QUEUE_EMPTY) { Log.v(TAG,"Download runnable queue is empty!"); } } } };
关于Android:对话框在单独的线程中获取输入时,等待线程的主线程和android四种对话框的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于Android .aidl中的单向声明是否可以保证在单独的线程中调用该方法?、android – MediaPlayer应该在单独的线程中运行吗?、android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?、android – 获取主线程的消息队列和处理程序等相关内容,可以在本站寻找。
本文标签: