0

我正在尝试使用旋转的 ProgressDialog 来告诉用户程序何时运行。我已经ProgressDialog正确地显示和关闭了,但是只有在调用之间有简单的代码时。我目前正在ProgressDialog我的onCreate方法中初始化,然后在按下按钮时,将显示对话框,然后遍历大量代码,然后是关闭调用。代码全部正确执行,但对话框从未显示。

public class Waves extends Activity {
    private ProgressDialog pd;
    public void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );
        pd = new ProgressDialog( this );  
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        pd.setMessage("Reading...");
        pd.setCancelable(false);
        setContentView( R.layout.waves );

        readButton = (Button) findViewById( R.id.readButton );
        readButton.setOnClickListener( new OnClickListener() {

        public void onClick(View arg0) {
            pd.show( );
            if( myService.getState() != 3 ) {
                myService.setHandler( mHandler );
                myService.connect( MainMenu.previousDevice, true );
            } else {
                readWaves();
            }
        }
    });

}

readWaves 如下所示。在 readWaves 的末尾pd.dismiss()是调用的地方。readWaves 中有许多函数调用,我将尝试在不冗长的情况下展示它们。

private void readWaves() {
    if( spinnerChoice == 0 ) {
        Log.i( "IN IF", "IN IF" );
        // Diff Voltage
        waveResults = RelayAPIModel.NativeCalls.GetWavesJava( RelayAPIModel.WAVES_V );
    } else {
        // Current 
        waveResults = RelayAPIModel.NativeCalls.GetWavesJava( RelayAPIModel.WAVES_I );
    }

    updateGraph();
    netV1Check.setChecked( true );
    netV2Check.setChecked( true );
    netV3Check.setChecked( true );
    vdi1Check.setChecked( true );
    vdi2Check.setChecked( true );
    vdi3Check.setChecked( true );
    hasRead = true;
    pd.dismiss();
}

updateGraph()调用对图表进行了简单的修饰,所以我认为问题不存在。RelayAPIModel.NativeCalls.GetWavesJava()电话是我认为问题出现的地方。

GetWavesJava()是一个用 C 语言编写的函数,位于我的本地库中。在 GetWavesJava() 中,有大量对其他本机 C 函数的函数调用,以及对我的应用程序 Java 端的大量函数调用。

这听起来很愚蠢,但原因是 C 中的本机库是需要使用的现有库。但是,它不支持Android的蓝牙功能,所以所有通过蓝牙发送/接收数据的方法都需要在Java端进行描述。

总共有六个用于 I/O 流的 Java 函数,它们在整个应用程序中被多次使用,而不仅仅是这一次调用。我考虑放入pd.dismiss()其中一个函数,但只需要 1% 的时间调用这些函数。

有谁知道确保我的对话框在本机函数调用之前显示并在之后停止的解决方案?

这是一个类似的 SO 问题,但不完全相同

编辑 :

使用下面的答案,这是我的代码:

readButton = (Button) findViewById( R.id.readButton );
readButton.setOnClickListener( new OnClickListener() {

        public void onClick(View arg0) {

            pd.show( );
            Thread export = new Thread() {  
                 public void run() {
                        if( myService.getState() != 3 ) {
                            Log.i( "myService", "12222" );
                            myService.setHandler( mHandler );
                            myService.connect( MainMenu.previousDevice, true );
                        } else {
                            Log.i("myService",  "32222" );
                            readWaves();
                            Log.i( "myService", "42222" );
                        }

                 mHandler.obtainMessage(MainMenu.READ_FINISHED );
                 }
            };
            export.start();
                        }
    });

Log( 42222 )永远达不到。微调器确实出现了,但程序会在几秒钟内崩溃并重新启动。我已.sendToTarget()在该mHandler.obtainMessage()行中添加,但这会导致没有微调器出现,并且程序崩溃。

编辑 2:

我还想补充一点,该readWaves函数使用现有的正在运行的线程来执行。我不确定这是否有什么不同

编辑 3:

在这里,我更新了初始提交的第二个代码块。使用此代码,进度对话框永远不会显示自己。代码执行时涉及的所有代码ProgressDialog根本不存在。

private void readWaves() {
    if( spinnerChoice == 0 ) {
        Log.i( "IN IF", "IN IF" );
        // Diff Voltage
        waveResults = RelayAPIModel.NativeCalls.GetWavesJava( RelayAPIModel.WAVES_V );
    } else {
        // Current 
        waveResults = RelayAPIModel.NativeCalls.GetWavesJava( RelayAPIModel.WAVES_I );
    }

    pd.dismiss();
    updateGraph();
    netV1Check.setChecked( true );
    netV2Check.setChecked( true );
    netV3Check.setChecked( true );
    vdi1Check.setChecked( true );
    vdi2Check.setChecked( true );
    vdi3Check.setChecked( true );
    hasRead = true;

}

编辑 4: 这是我最近的代码。ProgressDialog 显示在我想要的位置,但微调器不旋转。我曾尝试替换pd.dismiss()pd.hide()稍后pd.dismiss()放入代码,但这会导致对话框始终停留在屏幕上。自从.setCancelable(false)被使用后,我永远无法退出它。我还采用了pdonClickListener 外部的声明,因为我无法将参数传递this给. 我不记得我可以传递给它什么来让它工作,我试过了,但它们都没有奏效。ProgressDialogOnClickListenergetApplicationContext()ClassName.javaClassName.class

    readButton = (Button) findViewById( R.id.readButton );
    final ProgressDialog pd = new ProgressDialog( this );  
    readButton.setOnClickListener( new OnClickListener() {
        public void onClick(View arg0) {
            pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            pd.setMessage("Reading...");
            pd.setCancelable(false);            
            pd.show( );

            Thread export = new Thread() {  
                 public void run() {
                        if( myService.getState() != 3 ) {
                            Log.i( "myService", "12222" ); 
                            myService.setHandler( mHandler );
                            myService.connect( MainMenu.previousDevice, true );
                        } else {
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    readWaves();
                                }
                            });
                        }
                 mHandler.obtainMessage(MainMenu.READ_FINISHED ).sendToTarget();
                 pd.dismiss();
                 }
            };
            export.start(); 

编辑 5:试图让微调器出现在if语句中:

    readButton = (Button) findViewById( R.id.readButton );
    readButton.setOnClickListener( new OnClickListener() {
        public void onClick(View arg0) {
            final ProgressDialog pd = new ProgressDialog( Waves.this );  
            pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            pd.setMessage("Reading...");
            pd.setCancelable(false);            
            pd.show( );

            Thread export = new Thread() {  
                 public void run() {
                        if( myService.getState() != 3 ) {
                            Log.i( "myService", "12222" ); 
                            myService.setHandler( mHandler );
                            runOnUiThread( new Runnable() {
                                public void run() {
                                    myService.connect( MainMenu.previousDevice, true );
                                }
                            });
                        } else {
                            runOnUiThread(new Runnable() {
                                public void run() {
                                    readWaves();
                                }
                            });
                        }
                 mHandler.obtainMessage(MainMenu.READ_FINISHED ).sendToTarget();
                 pd.dismiss();
                 }
            };
            export.start();
4

2 回答 2

2

鉴于您已经提到All UI is updated within updateGraph(),您的代码(来自第二次编辑,大部分是正确的)正在抛出CalledFromWrongThreadException. 您的updateGraph()方法是从readWaves()方法中调用的,而该方法又是从new Thread()您创建的方法中调用的。这意味着您正在尝试从不是这些视图的实际父级的 Thread 更新某些视图。

尝试:

final ProgressDialog pd = new ProgressDialog( this );  
pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pd.setMessage("Reading...");
pd.setCancelable(false);            
pd.show( );
Thread export = new Thread() {  
    public void run() {
        if( myService.getState() != 3 ) {
            Log.i( "myService", "12222" );
                myService.setHandler( mHandler );
                myService.connect( MainMenu.previousDevice, true );
        } else {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    readWaves();
                }
            });
            pd.dismiss();
        }
        mHandler.obtainMessage(MainMenu.READ_FINISHED );
    }
}.start();

runOnUiThread()调用确保updateGraph()从内部readWaves()完成的 UI 更新在 UI 线程上完成。哦,你可以删除pd.dismiss().readWaves()

编辑:对于不旋转的微调器,这里有一个问题。解决方案说:

如果您关闭 Dialog,则不得再次显示相同的实例。要么创建一个新的,要么使用 hide() 而不是 dismiss()。使用 hide() 时,您仍然需要在不再需要时将其 dismiss()。

编辑

另请注意,在上面的代码中,我已将 ProgressDialog 的声明(在您的情况下是全局的)移动到onClick()事件处理程序的本地上下文中。这意味着为新的单击事件创建了一个新的 ProgressDialog。如果你以任何方式泄露了这种模式,请告诉我。

我不记得我可以传递给它什么来使它工作,我尝试了 getApplicationContext()、ClassName.java 和 ClassName.class,但它们都没有工作。

试试ClassName.this

于 2013-01-03T19:29:04.140 回答
0

这可能是异步问题,尝试显示对话然后使用异步处理程序来触发长任务(您的本机调用)。我也必须处理这个问题,因为有时像“解雇”/“显示”这样的事情会发布到消息队列中,然后你用长任务阻止它。尝试将线程用于长任务并且不要阻塞 UI

在这里查看我的博客文章:

Android中的进度对话

于 2012-12-28T18:52:56.440 回答