12

これは私のシナリオです:別のアクティビティを開くログイン画面があります。アクティビティでは、私は単純に以下を持っています:setContentViewでレイアウトをロード中にProgressDialogを表示

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_details); 
} 

レイアウトは重く、いくつかのフラグメントで構成されており、ロードに約1.5秒かかります。 がレイアウトを膨張させている間に、ProgressDialogを表示するにはどうすればよいですか?私はdoInBackgroundsetContentViewを入れてAsyncTaskを試しましたが、UIスレッドからのみUIを更新できるため、もちろんできません。 UIスレッドでsetContentViewに電話する必要がありますが、ProgressDialogを表示/非表示する必要はありますか?

ご協力いただきありがとうございます。

フラ。

EDIT:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_empty_layout); 
    new ContentSetterTask().execute(""); 
} 

private class ContentSetterTask extends AsyncTask<String, Void, Void> { 

    public ProgressDialog prgDlg; 

    @Override 
    protected void onPreExecute() { 
     android.os.Debug.waitForDebugger(); 
     prgDlg = ProgressDialog.show(MultiPaneActivity.this, "", "Loading...", true); 

    } 

@Override 
protected Void doInBackground(String... args) { 
    android.os.Debug.waitForDebugger(); 
    ViewGroup rootView = (ViewGroup)findViewById(R.id.emptyLayout); 
    LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    View inflated = inflater.inflate(R.layout.activity_details, rootView); 
    return null; 
} 

@Override 
protected void onPostExecute(Void arg) { 
    android.os.Debug.waitForDebugger(); 
    if (prgDlg.isShowing()) 
     prgDlg.dismiss(); 
    } 
    } 
} 

View inflated = inflater.inflate(R.layout.activity_details, rootView); 

は私にエラーを与える:私はこれは私が今持っているコードで、JohnBokerの以前の提案@続く

06-27 16:47:24.010: 
ERROR/AndroidRuntime(8830): Caused by:android.view.ViewRoot$CalledFromWrongThreadException: 
Only the original thread that created a view hierarchy can touch its views. 
+1

doInBackgroundメソッドで手動で膨張させるのはどうですか? –

+0

あなたのレイアウトファイルを見て興味深いでしょう、私が思うに最適化しようとするのが最適です。 エミュレータまたは携帯電話/タブレットで1.5秒かかりますか? – Marty

+0

こんにちは、実際には、eeePadトランスフォーマーで約1.5秒です。 どうすれば手動で膨らませることができますか? ここに投稿するレイアウトはかなり長いですが、約10-12の線形レイアウトと1つの実際のフラグメント(今のところ)があります。 – frapontillo

答えて

8

私は将来の読者のためにここで完全な答えを出すことにしました。 上で行われる必要がある 操作であるレイアウトを膨らませる

  1. が問題に費やした数時間後、私は、問題は、私は二つのことをやろうとしているであることに気づきましたUIスレッド。サービスが 任意のダイアログを表示することはできませんので、ダイアログ示す

  2. (ProgressDialogを、実際に が、これは 結果を変更しませんが)、そのは、UIスレッドのみ から行うことができます。

したがって、両方の呼び出しがUIスレッドから行われるため(onCreateまたはAsyncTaskは違いはありませんが、UIスレッドです)、最初の呼び出しは適切に表示されません。 ボトムライン:この問題は現在Androidで解決できません。 UIとやりとりするためのより良いAPIを得ることができたらいいなと思っています。

私は、レイアウトを変更して軽量化することでこの問題を解決します(可能な場合)! ありがとうございました!

+1

HandlerThreadを使用すると、手動で別のスレッドでビューを膨張させることができます。基本的にビューを膨張させるスレッドにはルーパーが必要です。 – techiServices

8

I重いビューを作成するときに同じ問題がありました。私がしたことは、XMLファイルにのみlinearlayoutを置き、setContenその上でtView、その後、私はasynctaskで実際のビューを作成し、dymanically linearlayoutにビューを追加しました。

このメソッドは機能しているようで、処理中に進捗ダイアログを表示することができました。

+0

ええ、それは完璧な選択肢のようです! –

+0

どうすればいいですか? – frapontillo

+0

スレッドパーツのAsyncTaskでhttp://developer.android.com/resources/articles/painless-threading.htmlを参照し、onPreExecuteに表示されている進行状況ダイアログを表示し、onPostExecuteで終了します。ビューを膨らませる例があります。http://stackoverflow.com/questions/5292328/once-a-view-is-inflated-dynamically-as-a-list-with-a-button-attached-to-each-行 –

0

これは完璧な解決策ではありませんが、私が必要とするものに最も近いものです:進行状況ダイアログ(またはメッセージ表示など)を表示してからsetContentView()を呼び出すまでに時間が必要です。メッセージが実際に表示されます。

これを達成するために、私は短いsleep()を実行してから、UIスレッドでsetContentView()を呼び出してスレッドを開始します。ここで

は進捗ダイアログを持つ例です。これで

private ProgressDialog m_Hourglass = null ; 
private Thread   m_LoadingThread = null ; 

... 

public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 

    ... 

    m_Hourglass = new ProgressDialog(this); 
    m_Hourglass.setMessage("Loading"); 
    m_Hourglass.setIndeterminate(true); 
    m_Hourglass.setCancelable(false); 
} 

public void SetMyView(View vvv)     // Can be called from buttons. 
{ 
    if(m_LoadingThread != null) return;   // Avoid multiple press 

    m_Hourglass.show(); 

    //////////////////////////////////////////////////// 
    // Load in a thread, just to show the above message 
    // before changing layout (because setContentView() 
    // freezes the GUI.) 
    m_LoadingThread = new Thread() 
    { 
      @Override 
      public void run() 
      { 
       super.run(); 
       try     { sleep(20); } 
       catch (Exception e) { System.out.println(e); } 
       finally    { runOnUiThread(new Runnable() 
             { 
              public void run() 
              { 
               SetMyViewThreaded(); 
              } 
             }); 
            } 
       m_LoadingThread = null ; // Now we can load again 
      } 
    }; 
    m_LoadingThread.start(); 
} 

public void SetMyViewThreaded() 
{ 
    setContentView(R.layout.some_gorgeous_layout); 

    ///////////////////////////////////////////////////// 
    // Catch when to finally hide the progress dialog: 
    ImageView iv   = (ImageView) findViewById(R.id.some_view_in_the_layout); 
    ViewTreeObserver obs = iv.getViewTreeObserver();  
    obs.addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
    {   
     @Override   
     public void onGlobalLayout() // The view is now loaded 
     { 
      m_Hourglass.hide(); 
     }  
    }); 

    ////////////////////////////////////////////////////// 
    // Here we can work on the layout 
    ... 
} 

私の主な問題は、近似値であり、すべてのマシン上では十分ではないかもしれない睡眠(20)、です。それは私にとっては効果的ですが、進行状況ダイアログが表示されない場合は、おそらくスリープ時間を長くする必要があります。

関連する問題