0

回転するProgressDialogを使用して、プログラムが動作していることをユーザーに通知しようとしています。をProgressDialog正しく表示および却下するようになりましたが、呼び出しの間に単純なコードがある場合に限ります。ProgressDialog現在、メソッド内で初期化を行っonCreateています。ボタンを押すと、ダイアログが表示され、多くのコードがトラバースされ、その後にdismiss呼び出しが続きます。コードはすべて正しく実行されますが、ダイアログは表示されません。

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のBluetooth機能はサポートされていないため、Bluetoothを介してデータを送受信するすべてのメソッドをJava側で記述する必要があります。

I / Oストリームに使用されるJava関数は全部で6つあり、これらは、この1回の呼び出しだけでなく、アプリケーション全体で何度も使用されます。それらの関数の1つを入れることを検討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:

ここでは、最初の送信から2番目のコードブロックを更新しました。このコードを使用すると、進行状況ダイアログが表示されることはありません。コードは、を含むすべてのコード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)使用されているので、私はそれを元に戻すことはできません。内に引数をpd渡すことができないため、onClickListenerの外の宣言も取得しました。私はそれを機能させるために何を渡すことができるかを覚えていません、私は試しました、しかしそれらのどれも機能しませんでした。thisProgressDialogOnClickListenergetApplicationContext()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()したとすると、あなたのコード(ほとんど正しい2番目の編集から)はを投げていCalledFromWrongThreadExceptionます。メソッドupdateGraph()はメソッドから呼び出され、メソッドは作成したreadWaves()メソッドから呼び出されnew 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()内部から実行されるUI更新がreadWaves()UIスレッドで実行されるようになります。pd.dismiss()ああ、あなたはの終わりにを削除することができますreadWaves()

編集:スピナーが回転しない場合は、ここに質問があります。ソリューションは言う:

ダイアログを閉じた場合、同じインスタンスを再度表示してはなりません。新しいものを作成するか、dismiss()の代わりにhide()を使用してください。hidden()を使用する場合でも、不要になったときに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 に答える