Android 无法从IntentService更新UI
一个看似简单的要求——从Android 无法从IntentService更新UI,android,android-intentservice,localbroadcastmanager,Android,Android Intentservice,Localbroadcastmanager,一个看似简单的要求——从IntentService更新用户界面。在下面的快照中,当单击开始服务按钮时,我需要在唯一的文本视图上方显示一个进度条,并在延迟后移除进度条 找到了很多答案,但不知何故还是无法破解。据我所知,LocalBroadcastManager是一个很好的方法。我还尝试了以下方法(一种使用处理程序s的方法),但它也无法显示进度条。最后,根据答案,以下是我的结论。到目前为止,我管理的输出只是在所有日志记录完成后连续出现的Toasts 非常感谢您能指出我的错误,我已经挣扎了很长时间了
IntentService
更新用户界面。在下面的快照中,当单击开始服务
按钮时,我需要在唯一的文本视图
上方显示一个进度条
,并在延迟后移除进度条
找到了很多答案,但不知何故还是无法破解。据我所知,LocalBroadcastManager
是一个很好的方法。我还尝试了以下方法(一种使用处理程序
s的方法),但它也无法显示进度条
。最后,根据答案,以下是我的结论。到目前为止,我管理的输出只是在所有日志记录完成后连续出现的Toast
s
非常感谢您能指出我的错误,我已经挣扎了很长时间了。非常感谢
main活动
更新
public class MainActivity extends AppCompatActivity
{
private static final String TAG = "MainActivity";
private ProgressBar pb;
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.pb);
myBroadcastReceiver = new MyBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(myBroadcastReceiver, new IntentFilter("ACTION"));
}
private void updateUI(boolean show)
{
if (show)
pb.setVisibility(View.VISIBLE);
else
pb.setVisibility(View.GONE);
// Toast.makeText(this, "UI Updated...", Toast.LENGTH_LONG).show();
}
public void startIt(View view)
{
Intent intent = new Intent(this, NanisIntentService.class);
startService(intent);
}
public class MyBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(final Context context, Intent intent)
{
String action = intent.getAction();
Log.e(TAG, "In onReceive(): " + action);
if (action.equals("ACTION"))
{
updateUI(true);
} // of if (action = "ACTION")
else if (action.equals("NOITCA"))
{
updateUI(false);
} // of else of if (action = "ACTION")
} // of onReceive()
} // of class MyBroadcastReceiver
}
public class NanisIntentService extends IntentService
{
private static final String TAG = "NanisIntentService";
public NanisIntentService()
{
super("NanisIntentService");
}
@Override
protected void onHandleIntent(Intent intent)
{
Log.e(TAG, "In onHandleIntent(): Intent is being serviced");
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
int i = 0;
while (i <= 50)
{
try
{
Thread.sleep(50);
i++;
Log.e("", "" + i);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
IntentService
已更新
public class MainActivity extends AppCompatActivity
{
private static final String TAG = "MainActivity";
private ProgressBar pb;
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pb = (ProgressBar) findViewById(R.id.pb);
myBroadcastReceiver = new MyBroadcastReceiver();
LocalBroadcastManager.getInstance(this).registerReceiver(myBroadcastReceiver, new IntentFilter("ACTION"));
}
private void updateUI(boolean show)
{
if (show)
pb.setVisibility(View.VISIBLE);
else
pb.setVisibility(View.GONE);
// Toast.makeText(this, "UI Updated...", Toast.LENGTH_LONG).show();
}
public void startIt(View view)
{
Intent intent = new Intent(this, NanisIntentService.class);
startService(intent);
}
public class MyBroadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(final Context context, Intent intent)
{
String action = intent.getAction();
Log.e(TAG, "In onReceive(): " + action);
if (action.equals("ACTION"))
{
updateUI(true);
} // of if (action = "ACTION")
else if (action.equals("NOITCA"))
{
updateUI(false);
} // of else of if (action = "ACTION")
} // of onReceive()
} // of class MyBroadcastReceiver
}
public class NanisIntentService extends IntentService
{
private static final String TAG = "NanisIntentService";
public NanisIntentService()
{
super("NanisIntentService");
}
@Override
protected void onHandleIntent(Intent intent)
{
Log.e(TAG, "In onHandleIntent(): Intent is being serviced");
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
int i = 0;
while (i <= 50)
{
try
{
Thread.sleep(50);
i++;
Log.e("", "" + i);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("ACTION"));
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
@Override
public void onDestroy()
{
super.onDestroy();
LocalBroadcastManager.getInstance(testing.com.myintentservice.NanisIntentService.this).sendBroadcast(new Intent().setAction("NOITCA"));
Log.e(TAG, "In onDestroy(): The service has been destroyed");
}
}
AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="testing.com.myintentservice.MainActivity">
<ProgressBar
android:id="@+id/pb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/tv"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="gone"/>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello IntentService!"
android:textColor="#1298CE"
android:textSize="32sp"/>
<Button
android:id="@+id/bt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="Start Service"
android:onClick="startIt"/>
</RelativeLayout>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="testing.com.myintentservice.NanisIntentService"/>
</application>
首先,您将占用主应用程序线程约2.5秒。这将在这段时间内冻结您的UI不要这样做 其次,在~2.5秒之前调用一次
updateUI()
,之后调用一次。由于您在这段时间内占用了主应用程序线程,因此这将产生与延迟后连续调用updateUI()
两次相同的视觉效果updateUI()
切换ProgressBar
可见性,因此两个调用将相互抵消,使您处于与启动时相同的状态
我需要在唯一的文本视图上方显示进度条,延迟一段时间后,删除进度条
显示一个ProgressBar
2.5秒,而不管实际做了什么工作,都是相当随意的
也就是说,调用
updateUI()
一次,然后使用pb.postDelayed()
计划Runnable
在2500毫秒后运行,其中Runnable
中的run()
方法第二次调用updateUI()
。这避免了阻塞主应用程序线程,因此它允许第一个updateUI()
调用生效,同时仍给您2.5秒的持续时间。首先,您将占用主应用程序线程约2.5秒。这将在这段时间内冻结您的UI不要这样做
其次,在~2.5秒之前调用一次updateUI()
,之后调用一次。由于您在这段时间内占用了主应用程序线程,因此这将产生与延迟后连续调用updateUI()
两次相同的视觉效果updateUI()
切换ProgressBar
可见性,因此两个调用将相互抵消,使您处于与启动时相同的状态
我需要在唯一的文本视图上方显示进度条,延迟一段时间后,删除进度条
显示一个ProgressBar
2.5秒,而不管实际做了什么工作,都是相当随意的
也就是说,调用
updateUI()
一次,然后使用pb.postDelayed()
计划Runnable
在2500毫秒后运行,其中Runnable
中的run()
方法第二次调用updateUI()
。这避免了您阻塞主应用程序线程,因此它允许第一个updateUI()
调用生效,同时仍给您2.5秒的持续时间。非常感谢,@commonware!终于成功了。我发现这两个不同的动作需要两个接收器
为了那些寻找最终工作代码的人的利益
请原谅代码中的任何复制粘贴鬼影,它毕竟是一个PoC,尽管功能强大。非常感谢,@commonware!终于成功了。我发现这两个不同的动作需要两个接收器 为了那些寻找最终工作代码的人的利益
请原谅代码中的任何复制粘贴鬼影,它毕竟是一个PoC,尽管功能强大。感谢您的快速响应,@commonware!抱歉,我没有提到这是一个实验,一个PoC-因此,不是2.5秒的延迟,而是一个不确定的internet下载,在此期间,我需要显示
ProgressBar
。你的建议仍然有效吗?如果您能在可能的情况下详细说明解决方案,我们将不胜感激。干杯@NarayanaJ:“你的建议仍然有效吗?”——假设ProgressBar
的持续时间是基于服务的,那么你也可以这样开始。对“显示”和“隐藏”使用两个不同的LocalBroadcastManager
事件。在短期内,将延迟放在服务中,以服务所做的“虚假工作”的形式。然后,您可以用真实的工作替换假工作,并且您的ProgressBar
逻辑不必更改。请检查我原始问题中更新的代码。我所做的是:-将“假工作”移动到IntentService
-为广播设置两个操作,一个显示,一个隐藏ProgressBar
,我既不确定是否仍应进行Runnable
调用(您最初建议的),也不确定该如何进行。ProgressBar
仍不显示。好心的