Skip to content

Commit fe1d983

Browse files
authored
[tizen_app_manager] Add threading to prevent app freezing (#521)
1 parent 9340e9a commit fe1d983

File tree

5 files changed

+65
-26
lines changed

5 files changed

+65
-26
lines changed

packages/tizen_app_manager/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.2.2
2+
3+
* Add threading to `AppManager.getInstalledApps` to prevent app freezing.
4+
15
## 0.2.1
26

37
* Revise the example app.

packages/tizen_app_manager/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ To use this package, add `tizen_app_manager` as a dependency in your `pubspec.ya
1010

1111
```yaml
1212
dependencies:
13-
tizen_app_manager: ^0.2.1
13+
tizen_app_manager: ^0.2.2
1414
```
1515
1616
### Retrieving current app info

packages/tizen_app_manager/example/lib/main.dart

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,14 @@ class _MyHomePageState extends State<MyHomePage> {
5353
child: Scaffold(
5454
appBar: AppBar(
5555
title: const Text('App Manager Demo'),
56-
bottom: const TabBar(tabs: <Tab>[
57-
Tab(text: 'This app'),
58-
Tab(text: 'App list'),
59-
Tab(text: 'App events'),
60-
]),
56+
bottom: const TabBar(
57+
isScrollable: true,
58+
tabs: <Tab>[
59+
Tab(text: 'This app'),
60+
Tab(text: 'App list'),
61+
Tab(text: 'App events'),
62+
],
63+
),
6164
),
6265
body: const TabBarView(
6366
children: <Widget>[
@@ -110,6 +113,8 @@ class _CurrentAppScreenState extends State<_CurrentAppScreen> {
110113
_infoTile('State', appContext.appState.name),
111114
],
112115
);
116+
} else if (snapshot.hasError) {
117+
return Center(child: Text(snapshot.error.toString()));
113118
} else {
114119
return const Center(child: CircularProgressIndicator());
115120
}
@@ -125,9 +130,15 @@ class _AppListScreen extends StatefulWidget {
125130
State<_AppListScreen> createState() => _AppListScreenState();
126131
}
127132

128-
class _AppListScreenState extends State<_AppListScreen> {
133+
class _AppListScreenState extends State<_AppListScreen>
134+
with AutomaticKeepAliveClientMixin {
135+
@override
136+
bool get wantKeepAlive => true;
137+
129138
@override
130139
Widget build(BuildContext context) {
140+
super.build(context);
141+
131142
return FutureBuilder<List<AppInfo>>(
132143
future: AppManager.getInstalledApps(),
133144
builder: (BuildContext context, AsyncSnapshot<List<AppInfo>> snapshot) {
@@ -155,6 +166,8 @@ class _AppListScreenState extends State<_AppListScreen> {
155166
);
156167
},
157168
);
169+
} else if (snapshot.hasError) {
170+
return Center(child: Text(snapshot.error.toString()));
158171
} else {
159172
return const Center(child: CircularProgressIndicator());
160173
}
@@ -182,12 +195,16 @@ class _AppEventsScreen extends StatefulWidget {
182195
State<_AppEventsScreen> createState() => _AppEventsScreenState();
183196
}
184197

185-
class _AppEventsScreenState extends State<_AppEventsScreen> {
198+
class _AppEventsScreenState extends State<_AppEventsScreen>
199+
with AutomaticKeepAliveClientMixin {
186200
late final StreamSubscription<AppRunningContext>? _launchSubscription;
187201
late final StreamSubscription<AppRunningContext>? _terminateSubscription;
188202
final List<_AppEvent> _appEvents = <_AppEvent>[];
189203
String _settingsAppId = settingsAppId;
190204

205+
@override
206+
bool get wantKeepAlive => true;
207+
191208
@override
192209
void initState() {
193210
super.initState();
@@ -230,6 +247,8 @@ class _AppEventsScreenState extends State<_AppEventsScreen> {
230247

231248
@override
232249
Widget build(BuildContext context) {
250+
super.build(context);
251+
233252
return Column(
234253
mainAxisSize: MainAxisSize.min,
235254
children: <Widget>[

packages/tizen_app_manager/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: tizen_app_manager
22
description: Tizen application manager APIs. Used for getting app info and getting app running context on a Tizen device.
33
homepage: https://github.com/flutter-tizen/plugins
44
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/tizen_app_manager
5-
version: 0.2.1
5+
version: 0.2.2
66

77
environment:
88
sdk: ">=2.15.1 <3.0.0"

packages/tizen_app_manager/tizen/src/tizen_app_manager_plugin.cc

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "tizen_app_manager_plugin.h"
66

7+
#include <Ecore.h>
78
#include <app.h>
89
#include <flutter/event_channel.h>
910
#include <flutter/event_sink.h>
@@ -253,23 +254,38 @@ class TizenAppManagerPlugin : public flutter::Plugin {
253254
}
254255

255256
void GetInstalledApps(std::unique_ptr<FlMethodResult> result) {
256-
flutter::EncodableList list;
257-
for (const auto &app_info :
258-
TizenAppManager::GetInstance().GetAllAppsInfo()) {
259-
AppInfoToEncodableMap(
260-
app_info.get(),
261-
[&list](flutter::EncodableMap map) {
262-
list.push_back(flutter::EncodableValue(map));
263-
},
264-
[app_info = app_info.get()](int error_code,
265-
std::string error_string) {
266-
std::optional<std::string> app_id = app_info->GetAppId();
267-
LOG_ERROR("Failed to get app info [%s]: %s",
268-
app_id.has_value() ? app_id->c_str() : "",
269-
error_string.c_str());
270-
});
271-
}
272-
result->Success(flutter::EncodableValue(list));
257+
// TizenAppManager::GetAllAppsInfo() is an expensive operation and might
258+
// cause unresponsiveness on low-end devices if run on the platform thread.
259+
ecore_thread_run(
260+
[](void *data, Ecore_Thread *thread) {
261+
auto *result = static_cast<FlMethodResult *>(data);
262+
263+
flutter::EncodableList list;
264+
for (const auto &app_info :
265+
TizenAppManager::GetInstance().GetAllAppsInfo()) {
266+
AppInfoToEncodableMap(
267+
app_info.get(),
268+
[&list](flutter::EncodableMap map) {
269+
list.push_back(flutter::EncodableValue(map));
270+
},
271+
[app_info = app_info.get()](int error_code,
272+
std::string error_string) {
273+
std::optional<std::string> app_id = app_info->GetAppId();
274+
LOG_ERROR("Failed to get app info [%s]: %s",
275+
app_id.has_value() ? app_id->c_str() : "",
276+
error_string.c_str());
277+
});
278+
}
279+
result->Success(flutter::EncodableValue(list));
280+
delete result;
281+
},
282+
nullptr,
283+
[](void *data, Ecore_Thread *thread) {
284+
auto *result = static_cast<FlMethodResult *>(data);
285+
result->Error("Operation failed", "Failed to start a thread.");
286+
delete result;
287+
},
288+
result.release());
273289
}
274290

275291
void IsAppRunning(const flutter::EncodableMap *arguments,

0 commit comments

Comments
 (0)