スマホアプリ開発初心者の備忘録
はじめに
こんにちは、カシオでアプリ開発をしている社会人4年目の野城です。
入社から、電子文具(ラベルライター)のソフト設計を担当しています。
1年目〜3年目 PC版(Windows/Mac) 「Label Design Maker」
4年目〜 スマホ版(Android/iOS)「Label Design Maker 2」
入社4年目からAndroid/iOSで配信されているアプリケーションの開発を担当することになりました。
その時に学んだ内容(メイン・バックグラウンド処理/同期・非同期処理)について、記録に残したいと思います。
Label Design Maker とは?
そもそも「LABEL DESIGN MAKER」とは何なのか説明させて下さい。
「LABEL DESIGN MAKER」は、短時間で簡単に、統一感のあるラベルを作ることができるアプリケーションです。
作成したラベルは、Bluetooth(R)や無線LANでカシオのラベルライターに送信して印刷することができます。これを読んでいる皆さんも、幼稚園の時に持ち物にラベルを貼ってもらった経験がある方もいるのではないでしょうか。
【カシオのラベルライターのラインナップ】
PCとスマートフォンでアプリをダウンロードできるので気になった方はダウンロードしてみて下さい。
開発にあたって・・・
アプリ開発者の仕事は、主にアプリケーションを操作するUIとラベルライターと端末(PC/スマホ)を通信する部分の開発になります。
初めてスマホアプリを開発するにあたって3冊の参考書を参考にしました。
データ構造とアルゴリズム・シリーズ1 データ構造
標準プログラマーズライブラリ C++クラスと継承完全制覇
新・明解C言語ポインタ完全攻略
これらの参考書を使って、同期・非同期やポインタについて学習しました。
スマートフォンアプリの開発環境は、それぞれ別のソフトウェアを使用しています。設計からテストまでを行うことができます。
Android版 Android Studio
iOS版 Xcode
Android/iOS共にGoogle PlayやApp storeにアプリをリリースするために大変なことは、開発環境がバージョンアップして使用していた関数の機能が使えなくなったり、AppleやGoogleでアプリをリリースするために追加の証明書が必要になったりすることです。
Appleのイベントで新製品の発表があるのを皆さんご存知かと思いますが、そのイベントでアプリ側で対応すべき条件が追加される時もあります。
例えば、2024年にAppleからアプリをリリースするためには「プライバシーマニフェスト」が義務化されました。
↑気になる方がいれば検索してみて下さい。
メイン処理とバックグラウンド処理について・・
スマホアプリ開発に携わるにあたってメイン処理とバックグラウンド処理について学習しました。
● メイン処理
メイン処理は、ユーザーインターフェース(UI)を操作するためのスレッドです。アプリの起動時に自動的に作成されユーザーからの入力(タップやスワイプ)の処理や画面の描画を担当しています。全てのUI更新はメインスレッドで行う必要がありますが、重い処理をここで行うとアプリがフリーズしてしまいます。
● バックグラウンド処理
バックグラウンド処理は、時間のかかる処理やリソース集約型のタスクを実行するスレッドです。ネットワーク通信、データベースアクセス、ファイルI/O等はバックグラウンドスレッドで実行するのが一般的です。
このバックグラウンド処理を用いることで、メイン処理が軽量なUI操作に専念でき、アプリのレスポンス性が向上します。
iOSの例
● メイン処理のプログラム例
DispatchQueue.main.async { ... } を使用して、UIの更新処理をメインスレッドで実行します。例として、ラベルのテキストを更新しています。
DispatchQueue.main.async {
// UIの更新処理
self.label.text = "Updated Text"
}
● バックグラウンド処理のプログラム例
DispatchQueue.global(qos: .background).async { ... } を使用して、重い処理をバックグラウンドスレッドで実行します。例として、ネットワークからデータを取得しています。バックグラウンドスレッドでデータを取得した後、その結果をメインスレッドでUIに反映させるために、再度DispatchQueue.main.async { ... } を使用します。
DispatchQueue.global(qos: .background).async {
// 重い処理(例:ネットワークリクエスト)
let url = URL(string: "https://example.com")!
let data = try? Data(contentsOf: url)
// UIの更新はメインスレッドで行う
DispatchQueue.main.async {
if let data = data {
self.imageView.image = UIImage(data: data)
} else {
self.label.text = "Failed to load data"
}
}
}
Androidの例
● メイン処理のプログラム例
runOnUiThread は Activity クラスのメソッドで、引数として Runnable を受け取ります。このメソッドは、指定された Runnable の中のコードをメインスレッドで実行します。この方法を使うことで、バックグラウンドスレッドから安全にUIを更新することができます。
runOnUiThread(new Runnable() {
@Override
public void run() {
// UIの更新処理
textView.setText("Updated Text");
}
});
● バックグランド処理のプログラム例
new Thread(new Runnable() { ... }).start(); を使って、新しいスレッドを作成し、バックグラウンドで重い処理を実行してrunOnUiThread メソッドを使って、バックグラウンドスレッドからメインスレッドでUIを更新します。
new Thread(new Runnable() {
@Override
public void run() {
// 重い処理
final Bitmap bitmap = loadImageFromNetwork(url);
// UIの更新はメインスレッドで行う
runOnUiThread(new Runnable() {
@Override
public void run() {
imageView.setImageBitmap(bitmap);
}
});
}
}).start();
同期処理と非同期処理について
同期処理とは、1つのタスクが完了するまで次のタスクが開始されない処理方法です。タスクは順番に実行され、各タスクが終了するまで他のタスクは実行されないのでエラーの発生箇所の特定がしやすいです。しかし、1つのタスクが長時間かかる場合、その間他のタスクが待機状態になるため効率が悪くなります。
同期処理のプログラム例
public class SynchronousExample {
public static void main(String[] args) {
task1();
task2();
}
public static void task1() {
System.out.println("Task 1 started");
try {
Thread.sleep(2000); // Simulate a time-consuming task
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task 1 completed");
}
public static void task2() {
System.out.println("Task 2 started");
System.out.println("Task 2 completed");
}
}
非同期処理は、同期処理とは異なり1つのタスクが完了するのを待たずに次のタスクを開始することができます。複数のタスクを同時に実行できるためリソースを有効活用できます。これにより、全体の処理時間を短縮することができますが、制御フローが並行処理のため、コードが複雑になりがちです。
非同期処理のプログラム例
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class AsynchronousExample {
public static void main(String[] args) {
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
task1();
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
task2();
});
try {
// Wait for both tasks to complete
CompletableFuture.allOf(future1, future2).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public static void task1() {
System.out.println("Task 1 started");
try {
Thread.sleep(2000); // Simulate a time-consuming task
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Task 1 completed");
}
public static void task2() {
System.out.println("Task 2 started");
System.out.println("Task 2 completed");
}
}
このプログラムは、”task1”と”task2”が並行して実行されます。
おわりに
ここまで読んでいただき、ありがとうございます。
スマホ開発1年目としての学んだ内容を記事にすることができて、とても良い経験になりました。まだまだ学ぶべき内容がたくさんあるので、これからもアプリ開発について学んで行きたいと思います。