我正在尝试使用旋转的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%。
有没有人知道一个解决方案,以确保我的对话框在本机函数调用之前显示,并在之后停止?
This is a similar SO question but not exactly the same
编辑:
使用下面的答案,这是我的代码:
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)
后,我就永远无法退出。我还在onClickListener之外接受了pd
的声明,因为我无法将参数this
传递给ProgressDialog
中的OnClickListener
。我不记得我可以传递给它以使它工作,我尝试了getApplicationContext()
,ClassName.java
和ClassName.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();
答案 0 :(得分:2)
鉴于您已经提到All UI is updated within updateGraph()
,您的代码(来自第二次编辑,大部分都是正确的)正在抛出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()
调用确保readWaves()
内pd.dismiss()
完成的UI更新是在UI线程上完成的。哦,你可以删除readWaves()
末尾的onClick()
。
编辑:对于不旋转的微调器,有一个question here。解决方案说:
如果您关闭对话框,则不得再次显示相同的实例。 创建一个新的,或使用hide()而不是dismiss()。什么时候 使用hide()时,你仍然需要在不再需要时解除()它。
修改强>:
另请注意,在上面的代码中,我已将ProgressDialog的声明(在您的情况下是全局的)移动到ClassName.this
事件处理程序的本地上下文。这意味着为新的click事件创建了一个新的ProgressDialog。如果你以任何方式泄露了这种模式,请告诉我。
我不记得我可以传递给它以使它工作,我试过 getApplicationContext(),ClassName.java和ClassName.class但没有 他们工作了。
尝试{{1}}。
答案 1 :(得分:0)
这可能是异步问题,尝试显示对话然后使用异步处理程序来解雇长任务(您的本机调用)。我也必须处理这个问题,因为有时像“dismiss”/“show”这样的东西发布到消息队列中,然后你用长任务来阻止它。尝试将线程用于长任务,不要阻止UI
请看我的博客文章: