Android アプリ開発で “cannot perform this action inside of onloadfinished” とエラーメッセージが表示された場面の対処法

公開日: : Android , ,

現在仕事で Android アプリ開発をやっていて、この “cannot perform this action inside of onloadfinished” のエラーに2度ほど出くわして調べるのに時間を使ったのでメモっておきます。

icatch-thread_11187402315_mini

photo credit: Tom Wachtel via photopin cc

目次

1. 動作環境

動作環境ですが、Android アプリの開発には次の IDE を使っています。

android-2014-02-18-00-1

2. エラーについて

“cannot perform this action inside of onloadfinished” というメッセージ内容から、非同期処理が終わったタイミングで実行しようとした処理でエラーが発生したことが分かるかと思います。

エラーの原因の前に非同期処理について、ちょっとメモしておきます。

2-1. 非同期処理のクラス関係について

以前は Android で非同期処理といえば AsyncTask を使っていましたが、最近は AsyncTaskLoader に取って代わっているようです(最近といっても2年ぐらい経過してるでしょうか)。

で、この AsyncTaskLoader を継承したクラスで非同期処理を実装し、そのクラスを LoaderManager.LoaderCallbacks インタフェースを implements したクラスが呼び出すって図式になっているようです。

この辺りは、次のサイトに特にお世話になりました。

ボクがコーディング中のクラスもこの関係のようになってまして、LoaderManager.LoaderCallbacks#onLoadFinished(loader, data) メソッド内で、このエラーが発生しました。

2-2. エラーの原因

さてエラーの原因です。

このエラーは GUI に関する操作をメインスレッド以外のスレッドから行おうとした場合に発生するものです。
少なくともボクが今まで体験した範囲内ではコレが原因でした。

この GUI やらメインスレッドの関係は、次のサイトの冒頭の件で雰囲気が掴めるかと思います。

上記サイトの言葉を借りると、GUI の処理をワーカースレッドで行ったからエラーが発生したということになります。

3. エラーの解消方法

エラーの解決方法ですが、「android ui スレッド」とかで検索すると盛りだくさんに見つかるのですが、それらとは少し違う部分があるのでコードスニペットなどを載せておきます。

3-1. コードスニペット

まずはコードスニペットからです。

public void hoge() {
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        @Override
        public void run() {
            // GUI に関する何かしらの処理をここに実装する
        }
    });
}

一見よく見かける対処法のコードですが、Handler クラスを生成するコンストラクタの部分が違います。

多くのサイトではデフォルトコンストラクタを使っていますが、Looper クラスを受け取るコンストラクタを使います。

3-2. Hander クラスと Looper クラスについて

この HandlerLooper クラスですが、次のサイトに図で説明してくれています。

以下は引用です。

UIの処理はLooperが実質的に行う

Androidプログラミングの館

このqueueに積む処理をHandlerによって実現することができるのです。

Androidプログラミングの館

非常に分かりやすい。

3-3. Hander クラスのコンストラクタは Looper を受け取るものを使う

先ほどのコードスニペットにもあるように Handler クラスを生成する際のコンストラクタは Looper クラスを受け取るものを使うのがベストです。

理由は次のサイトから引用させてもらいます。

Handlerクラスは決してUIスレッドへRunnableを送りつけるためのものではない。Handlerインスタンスを生成したスレッドへイベントを送りつけるための仕組みである。

Runnableを送りつけたい宛先を明示したい場合は、もう一つのコンストラクタであるHandler(Looper looper)を使う。これを使えば、任意のThreadへRunnableを送りつけることができる。

Handlerクラスの正しい使い方(Androidでスレッド間通信) – ちくたく

ちなみにUIスレッドのLooperを取得したい場合は、Looper.getMainLooper()を呼べばよい。

Handlerクラスの正しい使い方(Androidでスレッド間通信) – ちくたく

ここで言っている「UIスレッド」というのは、上記に書いた「メインスレッド」と同じものを指しています。

Looper.getMainLooper() でメインスレッドを取り出して明示的に Hander クラスに渡す」というコードのほうがより正確であるため、Hander クラスを生成する際には Looper を受け取るコンストラクタを使いましょう、ということでした。

4. まとめ

Android、なかなか奥が深いです。

スマホ案件は儲からないので会社として力を入れていないこともあって、あまり勉強してないのですがちょっと考えを改にしました。。。

5. その他の Android に関する記事

その他の Android に関する記事は次の通りです。
気になる記事があったらぜひチェックしてみてください!

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

icatch-bar_7241902618_mini

Android アプリで ActionBar の背景色を変更する方法

Android 3.x 系から追加された ActionBar。 開発中の Android アプリで

記事を読む

icatch-error_9849183645_mini

Android の非同期処理を行う Loader の起動方法

これ、ボクの完全な思い違いだったのですが、非同期処理を行うクラスの呼び出しは Activity か

記事を読む

icatch-timezone

Android アプリでタイムゾーンを Asia/Tokyo で現在時刻を取得する

もしかしたら環境だったり、条件があるのかもしれないけど備忘録としてメモ。 Android アプ

記事を読む

no image

WebView からデフォルトブラウザを開く

WebView に表示されているリンクは WebView ではなくデフォルトブラウザで開きたい、とい

記事を読む

no image

位置情報取得に関する覚え書き、その2

以前、【Androidアプリ開発】位置情報取得に関する覚え書き を書いたが、試行錯誤を続ける中で変更

記事を読む

no image

AlertDialog がキャンセルされたときに処理を行うスニペット

AlertDialog のスニペット。キャンセル時のリスナーを Gist に登録。 new Al

記事を読む

no image

位置情報取得に関する覚え書き

思うように最新の位置情報を取得できなかったが、試行錯誤した結果「とりあえず大丈夫かな」って段階まで持

記事を読む

icach-smartphone_10858946293_mini

Android アプリで “external/chromium/net/disk_cache/stat_hub.cc:216″ とエラーメッセージが表示された場合の対処法

Android アプリ開発中にとある画面を表示しようとしたら "external/chromium/

記事を読む

no image

初めてのアンドロイドアプリ開発振り返り

始めてのアンドロイドアプリ開発が落ち着きをみせてきた。まだ熱が冷めないうちに簡単に振り返っておく。

記事を読む

icatch-android_6051805616_mini

Android アプリ開発で “Unable to resolve target ‘android-16′” などとエラーメッセージが表示された場合の対処法

"Unable to resolve target 'android-16'" などとエラーメッセー

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


8 × 九 =

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑