android - Android 和长时间运行的后台任务
问题描述
我有一个 Xamarin Android 应用程序。我需要在这个应用程序中开始长时间运行的任务。据我所知,我应该为此使用课程Service
。我创建了一个这样的类:
[Service]
public class BackgroundService : IntentService
{
Handler mHandler;
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
mHandler = new Handler();
SomeTask();
return 0;
}
private void SomeTask()
{
// Thread.CurrentThread.ManagedThreadId here is 1
Thread.Sleep(5000);
for (int i = 1; i <= 10; i++)
{
mHandler.Post(new Runnable(() =>
{
Toast.MakeText(this, $"Current thread ID in service: {Thread.CurrentThread.ManagedThreadId}", ToastLength.Short).Show();
}));
}
StopSelf();
}
protected override void OnHandleIntent(Intent intent)
{
}
}
以及我如何在活动中使用该服务:
// And here Thread.CurrentThread.ManagedThreadId is 1
var serviceToStart = new Intent(this, typeof(BackgroundService));
StartService(serviceToStart);
我希望该服务在另一个后台线程中启动,但Thread.CurrentThread.ManagedThreadId
在活动中与类 BackgroundService的Thread.CurrentThread.ManagedThreadId
in 方法相同。SomeTask
此外,当SomeTask
我的应用程序运行时没有响应。显然这意味着该服务在后台线程中不起作用。如何使服务在后台线程/进程中运行?
解决方案
您应该在方法中弹出 ToastOnHandleIntent
并将代码更改new Handler()
为new Handler(Looper.MainLooper)
.
你可以参考下面的demo。
IntentServiceDemo.cs
[Service]
public class IntentServiceDemo : IntentService
{
Handler mHandler;
public IntentServiceDemo() : base("IntentServiceDemo")
{
}
protected override void OnHandleIntent(Intent intent)
{
mHandler = new Handler(Looper.MainLooper);
SomeTask();
}
private void SomeTask()
{
Thread.Sleep(1000);
int id=System.Threading.Thread.CurrentThread.ManagedThreadId;
for (int i = 1; i <= 10; i++)
{
mHandler.Post(new Runnable(() =>
{
Toast.MakeText(ApplicationContext, $"Current thread ID in service:"+ id, ToastLength.Short).Show();
}));
}
StopSelf();
}
}
MainActivity.cs
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
//string TAG = "DemoService:";
// private Messenger messenger; // Instance variable for the Messenger
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_main);
int id = System.Threading.Thread.CurrentThread.ManagedThreadId;
Toast.MakeText(this ,"Main thread"+ id, ToastLength.Short).Show();
Button bt_service = FindViewById<Button>(Resource.Id.bt_service);
bt_service.Click += (e, o) =>
{
Intent downloadIntent = new Intent(this, typeof(IntentServiceDemo));
StartService(downloadIntent);
};
}
activity_main.axml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/bt_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="startService"/>
</RelativeLayout>
推荐阅读
- javascript - 将自定义图像上传到 Spotify 播放列表
- ios - react-native-maps initialRegion、region 和 animateToRegion 不适用于 iOS 但适用于 Android
- mysql - 需要创建一个长度为 60000 的 varchar 列
- sql - (SQL) 如何使用 xp_dirtree 获取文件名和大小?
- javascript - CSS 变量 Polyfil - 用于 LitePicker JS 的 IE11
- c# - System.InvalidCastException 与 iennumrable 演员
- android-studio - 不推荐使用 setDrawerLayout(androidx.drawerlayout.widget.DrawerLayout)
- mongodb - 如何在一次查询中根据 Mongoose(MongoDB)中的日期获取客户计数?
- reactjs - 减速器和状态之间的类型错误
- laravel - laravel 设置 ckeditor/ckeditor5-export-pdf