長期間の操作中の画面の回転

はじめに


ユーザーインターフェイスを備えたほとんどすべてのアプリケーションを開発する場合、プログラマーは遅かれ早かれ、長期間の操作を実行する必要がある状況に遭遇します。 長期間の操作中、通常、ユーザーには「お待ちください...」ウィンドウなどが表示されます。

Androidプラットフォーム、およびおそらく他の多くのプラットフォームでは、UIストリームでの長期操作が許可されていません。 UIスレッドで長期間の操作を実行すると、単にプログラムがハングします。

Androidは、この種のタスク用にAsyncTaskを提供しています。 AsyncTaskを使用すると、長期間の操作を実行し、UIスレッドと対話できます。

問題


AsyncTaskを作成し、作成したAsyncTaskに現在のアクティビティへのポインターを渡すだけで、バックグラウンドプロセスが実行され、UIが更新され、誰もが幸せになります。

画面の向き(縦→横、横→縦)またはアプリケーションが背景に送信されるまで、すべてが正常に機能します。 通常、このアプローチでは、画面の向きを変更した後、アプリケーションがクラッシュします。

アプリケーションがクラッシュするのはなぜですか?


Eranの方向を変更すると、Androidがアクティビティを再作成するため、結果として、AsyncTaskへのリンクを渡したアクティビティは既に破棄され、AsyncTaskは破棄されたオブジェクトとやり取りしようとしています。

解決策


誰もがさまざまな方法で問題を解決しますが、提案されたすべての解決方法については説明しません。さまざまなブログまたはStackOverflowでGoogleで見つけることができます。

各アプローチには、特定の調整、追加のテスト、デバッグ、追加のコードの記述、またはユーザーインターフェイスの機能の制限の実装が必要です。
この問題に直面して、私はそのような些細な作業のために既成のボックス化されたソリューションがないことに非常に悩まされました(いずれにしても、私はそれを見つけませんでした)。

試してもいいですか


厳密に判断せず、自己PRとは考えないでください。この問題をどのように解決するかを書き、解決策を他の人と共有したいだけです。

ある種のフレームワークを書いて(フレームワークは私のソリューションには大きすぎると思いますが、使用の特殊性のため、それはまだ一種のフレームワークです)、それをGithubに投稿しました。

ソースコードは公開されており、Apache 2.0ライセンスです 。また、私は何も販売せず、強要せず、懇願しません。 このフレームワークはAsmykと呼ばれます

仕組み


アクティビティがアクティブになると(onResumeイベント)、アクティビティはアプリケーションコンテキストでマークされます。 次に、バックグラウンドタスクは、コンテキストからアクティビティタスクのUIに対応します。

はい、複雑なことはありませんが、このスキームを実装する場合、初心者のプログラマは少し複雑になる可能性があり、高品質のソリューションを実装するために数日を費やす必要があります。

実装方法


AARファイルをダウンロードして、プロジェクトに接続します。

実装でApplicationクラスを拡張しない場合は、applicationタグのAndroidManifest.xmlファイルで属性を指定します。

android:name="net.mabramyan.asmyk.core.AsmykApplicationContext" 

例:

 <application ... android:name="net.mabramyan.asmyk.core.AsmykApplicationContext" ... > ... 

Applicationクラスを実装で拡張する場合、AsmykApplicationContextクラスから実装を継承する必要があります。

バックグラウンドで作業するアクティビティは、AsmykCompatActivitiyから継承する必要があります。
注: AsmykCompatActivitiyから少なくともすべてのアクティビティを継承できます。


UI「お待​​ちください...」


AsmykPleaseWaitActivityまたはAsmykBasicPleaseWaitActivityから継承されたアクティビティを作成します。

AsmykPleaseWaitActivityに実装する必要があるもの


このメソッドは、操作のステータスを更新するときにアクティビティが実行する必要があるアクションを記述します。 progressObjオブジェクトは、AsmykPleaseWaitTaskから渡されます。

 void onProgress(final Object progressObj) 

このメソッドは、操作が失敗したときにアクティビティが実行するアクションを記述します。 errorObjオブジェクトは、AsmykPleaseWaitTaskから渡されます。

 void onFail(final Object errorObj) 

メソッドは、操作が成功したときにアクティビティが実行するアクションを記述します。 successObjオブジェクトは、AsmykPleaseWaitTaskから渡されます。

 void onSuccess(final Object successObj) 

AsmykBasicPleaseWaitActivityに実装する必要があるもの


メソッドは、操作が成功したときにアクティビティが実行するアクションを記述します。 successObjオブジェクトは、AsmykPleaseWaitTaskから渡されます。

 void onSuccess(final Object successObj) 

onFailメソッドとonProgressメソッドは既に実装されています。 引数として、エラーの説明またはバックグラウンドタスクの新しい状態の説明を含むStringをそれぞれ受け入れます。

バックグラウンドタスク


次に、AsmykPleaseWaitTaskクラスを実装してバックグラウンドタスクを作成します。 バックグラウンドタスクを記述するメソッドを1つだけ実装する必要があります。

 void doInBackground(final AsmykApplicationContext ctx) 

タスクの実行中に、 void fireProgress(AsmykApplicationContext ctx, final Object progressObj)メソッドvoid fireProgress(AsmykApplicationContext ctx, final Object progressObj)を呼び出すことができます。このメソッドは、その後、AsmykPleaseWaitActivityでonProgressを呼び出します。 タスクが完了したら、操作の結果に応じて、fireSuccessメソッドまたはfireFailedメソッドを呼び出します。

打ち上げ


バックグラウンドタスクを呼び出す例:

 pleaseWaitTask.start((AsmykApplicationContext) MainActivity.this.getApplicationContext()); Intent intent = new Intent(MainActivity.this, PleaseWaitActivity.class); startActivity(intent); 

重要: AsmykPleaseWaitTaskityは、AsmykPleaseWaitActivityから継承されたアクティビティが表示された後にのみ実際にタスクを開始します。

これは、アクティビティが表示される前にバックグラウンドタスクが完了しないようにするためです。

ここで簡単なアプリケーションの例を見ることができます

コメンターへのアピール


読んでコメントしてくれてありがとう。
それが建設的なものである場合、私は批判のためです。
投稿が他の読者に役立つように、これをしましょう:
コード構造が正しくないと思われる場合は、その理由を説明してください。
上記の方法よりも便利または正しい方法を提供する場合、問題に解決策を適用します(これは上記のフレームワークが解決する主なタスクです)。
1)登録のためにユーザーからデータの一部をすでに受信している場合、ユーザーは「続行」をクリックします
2)登録手順1を実行します。N個の異なる要求が連続して送信されます。 ここでは、プログラムが今何をしているかをユーザーに示したいと思います。 この場合、画面の回転など。 登録プロセスを中断してはなりません。
私の観点からすると、実際のアプリケーションにはこのようなタスクが数多く存在する可能性があります。

PS実際の例を適用すると、投稿はできる限り役に立つと思います。

私はそれをすべて持っています! ご清聴ありがとうございました。

Source: https://habr.com/ru/post/J330646/


All Articles