0

編集:解決しました。申し訳ありませんが、データの読み込みがバックグラウンド スレッドで行われているときに、データを解析するコールバックがそうではないことに気付きました。データの解析には非常に長い時間がかかり、それがスレッドをロックしていました。

編集: 私の包括的な問題 (ProgressDialog が回転しなくなった) は、UI スレッドがブロックされているのではなく、ProgressDialog の使用の問題が原因である可能性があることに気付きました。その場合、どうすれば修正できますか?

編集:明確にするために、これはプログラム全体を永久にロックしません。すべてがロードされると、進行状況ダイアログは閉じられ、新しいアクティビティが表示されます。私の問題は、ロード中にUI全体がロックされることです(つまり、進行状況ダイアログの回転が停止します)

TL;DR: doInBackground() の Thread.sleep() が UI スレッドをロックしています

特定のアクティビティが開始されると、バックエンドから大量のデータ (スケジュールに関連する大量のデータなど) をバックグラウンドでロードし始めるアプリがあります。この情報はすぐには使用されませんが、ユーザーがアクセスしようとすると (つまり、スケジュール ボタンをクリックしてスケジュール アクティビティを起動することにより) 使用される可能性があります。

ユーザーが少し待ってからスケジュール ボタンをクリックすると、すべてのデータが読み込まれ、スケジュール アクティビティが開き、すべてが表示されます。私の問題は、データが読み込まれる前にボタンをクリックした場合です。

ここでの私の解決策は、データの読み込みが完了したかどうかを定期的にチェックし、それ以外の場合はスリープしている間に ProgressDialog を表示する ASyncTask を作成することでした。アプリケーション全体のブール変数を介して、データのロードが完了したことを認識しています。私の問題は、Thread.sleep() が doinbackground() 内で実行されていても、UI スレッドをロックしていることです。

以下に定義するカスタム ASyncTask を使用しています。

public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{
    private ProgressDialog pd; //the progress dialog
    private String title; //the title of the progress dialog
    private String  message; //the body of the progress dialog
    private Runnable task; //contains the code we want to run in the background
    private Runnable postTask; //execute when the task ends
    private Context c;


    public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){
        super();
        c = context;
        task = r;
        postTask = postR;
        title = t;
        message = m;
    }

    @Override
    protected void onPreExecute(){
        pd = ProgressDialog.show(c,title, message, false, false);
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        task.run();
        return true;
    }


    @Override
    protected void onPostExecute(Boolean result) {
        pd.dismiss();
        if(postTask != null)
            postTask.run();
    }

そしてそれを(例えば)経由で呼び出します:

if(loadingSchedule){

            LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() {
                public void run(){
                    while(loadingSchedule){
                            try {
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }

                    }
                }
            },new Runnable() {
                public void run(){

                    Intent i= new Intent(thisClass, Schedule.class);
                    i.putExtra("numberIneed",index);
                    startActivity(i); 
                }
            });
            lwpd.execute();

(読みやすくするために、グローバル変数へのアクセスを「loadingSchedule」に短縮しました)

これをUIスレッドをロックしないようにするにはどうすればよいですか?

4

2 に答える 2

5

doInBackground() の Thread.sleep() が UI スレッドをロックしています

doInBackground() 内の Thread.sleep() は、UI スレッドをロックしません。その名前が示すように、タスクはバックグラウンドで非同期的に実行されます。

UI スレッドはロックされません。実際には、AsyncTask が開始される前 (onPreExecute() メソッド内) に ProgressDialog ポップアップが表示され、AsyncTask の実行中 (doInBackground() メソッド内) に基になるアクティビティとのユーザー インタラクションが前面に表示され、ブロックされます。AsyncTask の終了後に最終的に却下されます。(onPostExecute() メソッド内)

特定のアクティビティが開くと、バックエンドからバックグラウンドで大量のデータをロードし始めるアプリがあります

これは一般的な使用例です。データの読み込みが完了したかどうかを定期的にチェックし、それ以外の場合はスリープしている間に ProgressDialog を表示する ASyncTask を作成する代わりに、バックグラウンドでデータを読み込む AsyncTask 実装を作成する方が効率的です。

ここでAPI を確認してください。適切に使用する方法の良い例が含まれています。

于 2012-02-15T00:19:47.350 に答える
0

あなたのコードは正しいように見え、メイン スレッドをブロックするべきではありません。

だからデバッガを使おう!lwpd.execute の後の doInBackground、Thread.sleep、onPostExecute にブレークポイントを配置すると、コードがいつどこで取得されるかがわかります。

「UIスレッドがブロックされている正確な場所」に対する答えを見つけてみてください。

于 2012-02-14T23:06:55.090 に答える