GVKun编程网logo

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

23

在本文中,您将会了解到关于Android:对话框在单独的线程中获取输入时,等待线程的主线程的新资讯,同时我们还将为您解释android四种对话框的相关在本文中,我们将带你探索Android:对话框在单

在本文中,您将会了解到关于Android:对话框在单独的线程中获取输入时,等待线程的主线程的新资讯,同时我们还将为您解释android四种对话框的相关在本文中,我们将带你探索Android:对话框在单独的线程中获取输入时,等待线程的主线程的奥秘,分析android四种对话框的特点,并给出一些关于Android .aidl中的单向声明是否可以保证在单独的线程中调用该方法?、android – MediaPlayer应该在单独的线程中运行吗?、android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?、android – 获取主线程的消息队列和处理程序的实用技巧。

本文目录一览:

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 .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应该在单独的线程中运行吗?

android – MediaPlayer应该在单独的线程中运行吗?

我正在构建一个从Web服务器流式传输音乐的应用程序.该应用程序具有使用MediaPlayer播放的前台服务.

我的代码是基于这个例子:http://developer.android.com/guide/topics/media/mediaplayer.html

在该示例中,除了prepareAsync()调用之外,没有任何内容是线程.令我困惑的是,当我阅读关于Service类的时候,我发现这个信息:

“注意:一个服务在其主机进程的主线程中运行 – 该服务不会创建自己的线程,并且不会在单独的进程中运行(除非另有指定),这意味着如果您的服务将执行任何cpu密集型工作或阻塞操作(如MP3播放或网络连接)时,您应该在服务中创建一个新的线程来完成此工作,通过使用单独的线程可以降低应用程序无响应(ANR)错误的风险,应用程序的主线程可以保持专用于与您的活动的用户交互.

我问的原因是应用程序有时候(通常当断开连接时)在流式传输音频时冻结UI.我完全明白,由于活动和服务运行在同一个线程上,因此服务使cpu变得更加强大,UI会冻结.但是,我应该期望MediaPlayer是如此激烈?那就是应该在单独的线程上运行吗?

解决方法

不幸的是,调用prepareAsync()并不足以避免ANR提示和您的应用程序挂起几秒钟,尤其是从网络播放文件时.最好的办法是将MediaPlayer的实例放在自己的线程中,或者至少在Handler中执行密集的调用(如mediaplayer.start()).我一直在使用MediaPlayer一年多,根据具体情况,我可以告诉你,在各种电话之后,它肯定会挂起来.

android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?

android – 应该在服务中完成对内容解析器的调用(即单独的线程)吗?

我正在更多地了解 Android中的内容提供商,而且他们的表现也是如此.例如,如果我为sqlite操作编写自己的内容提供程序(子类ContentProvider),然后我想在Activity的onPause()方法中执行操作,那么在我的Activity中我会这样做:

@Override
protected void onPause (){
    super.onPause();

    // ...prepare myTransactionValues

    // This Could be anything like insert,bulkInsert,query,delete,etc.
    getContentResolver().insert(CONTENT_URI,myTransactionValues)
}

但是,看起来这个数据库操作正在主线程上完成.工作是在幕后的一个单独的线程中完成的吗?它应该在它自己的线程中吗?如果应该,是否有推荐的方式(也许是服务)?

解决方法

如果您想在非UI线程中执行某些操作,通常应使用 AsyncTask.另一方面,服务最好用于长期任务.

android – 获取主线程的消息队列和处理程序

android – 获取主线程的消息队列和处理程序

如何从另一个线程获取主线程的消息队列? Looper.getMainLooper()获取主线程的looper但我无法找到另一种线程的looper获取MessageQueue的方法.而且,我如何获得主循环器的处理程序?我无法找到任何方法来获得它.

解决方法

@ r.v,

我有类似的需求.我想知道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 – 获取主线程的消息队列和处理程序等相关内容,可以在本站寻找。

本文标签: