8

メイン UI スレッド (関連する質問)で StackOverflowErrors に苦労しています。私のアプリは Android 2.3 以降を対象としています。Android 4 ではすべて問題ありませんが、2.3.3 でビュー レイアウトを描画するとクラッシュします。

明白な答えは、ビュー レイアウトを最適化し、ネストされたビューの数を減らすことです。これは問題です。ビューの数が多いのは、サポート ライブラリとタブのフラグメントを使用しているためです。これは推奨されるアプローチです。古いバージョンの OS ではスタックが小さいという理由だけで、設計を変更してフラグメントをドロップしたくありません。

UI スレッドのスタック サイズを増やす方法を探しています。これは不可能であるという回答を見てきましたが、マニフェストにそうするための簡単な設定がないことを理解しています。しかし、手動による回避策がないことにまだ満足していません。

これまでの私の最高のアイデア:

より大きなスタックで新しいワーカー スレッド (Thread クラス) を作成します。ワーカー スレッドのスタック サイズを増やすことができます。次に、このスレッドを何らかの方法で新しい UI スレッドに変換します。どのように?

  • android.app.Activity .attach(..)の Android ソースを参照すると、アクティビティが UI スレッドにアタッチされていることがわかりました。接続されているスレッドを置き換えて、「新しい」UIスレッドに変更する方法があるかもしれません

  • android.app.ActivityThread .startActivityNow(..)をもう少し掘り下げると、アクティビティを手動で開始できるようになるかもしれません。アクティビティが作成されると、作成されたスレッドに自動的にアタッチされます。新しい UI スレッドからこれを実行すると、うまくいくかもしれません。

  • 新しい UI スレッドを作成する場合、そのためのルーパーを手動で作成する必要があります。android.app.ActivityThread .main(..)から作成する必要があるものを感じています

その他のアイデア:

  • StackOverflowError を手動でキャッチし、それが発生した場合は呼び出しを非同期に移動して、スタックが小さくなるようにします。ここでこの素晴らしいアイデアを見てきましたが、機能させることができませんでした。

  • NDK スレッド (JNI 経由) には大きなスタックがあります。私は自分の利益のためにそれらを使用することを考えましたが、これを行う方法がわかりません. JNI 経由の呼び出しはすべて独自のスレッドで実行されるため、UI アクセスに NDK スレッドを使用する方法がわかりません。

そう..

これはまったく悪い考えだと言うことを除いて、他の提案やヒントはありますか? 似たようなことをした人を見つけることができますか?私はできませんでした..

4

2 に答える 2

2

CommonsWare は悲しいことに間違っています。詳しく調べてみると、Android 2.x のデフォルトのスタック サイズは 12KB で、Android 4.x では 16KB に増加しています。これは、コア チームが小さなスタックの問題を認識して修正したことを意味します。悲しいことに、これらの余分な 4KB がクラッシュのすべての違いを生むのです。

さらに、ABS などの一般的なライブラリを使用し、v4 をサポートしている場合、これらのライブラリは、フラグメントを使用するたびにレイアウトに追加のビューを追加します。私たちのほとんどはこれらのライブラリに依存しているため、1 つのビューでフラグメントを簡単に追加できると言うのは正しくありません。ABS+support lib を使用している場合、フラグメントごとに 3 ビューを支払う必要があります。また、最低 5 つのビューから始めます (ABS レイアウトの場合)。

UI スレッドを手動で作成することに関しては、これは可能であり、おそらくデバイスをルート化したり、ファームウェアを変更したりする必要はありません。これらは、おそらく正しくない大胆なステートメントでもあります。

最後に、大きなスタックを持つ独自の UI スレッドを作成しないことにしました。代わりに、コードからフラグメントの使用を完全に削除することにしました。これにより、レイアウトで合計 5 つのビューを節約できました。フラグメントが提供するものはすべて、ViewGroups を手動で追加することによっても実行できます。コードが少し増えただけですが、それほど複雑ではありません。フラグメントは少し役に立たないようです。それらを使用する余裕がない場合は、最初にカットする場所です。

于 2013-06-06T15:11:23.227 に答える
-1

Android 4ではすべて問題ありません

いいえ、あなたはまだ墜落していません。Android 4.x でスタック サイズを増やしたことは知りません。一部のウィジェットがもう少し効率的になった可能性があります。これにより、一部の操作で、もう少し長く生き残ることができます。

これは問題です。多数のビューは、サポート ライブラリとタブのフラグメントを使用しているためです。これは推奨されるアプローチです。

Viewsそれらのタブが(および適切なViewPagerインジケーター)、アクション バー、または古代のTabHost. フラグメントは必要ありません。

UI スレッドのスタック サイズを増やす方法を探しています

これは、Android フレームワークを変更し、最大 8 億の Android デバイス ユーザーに銃口を突きつけて携帯電話をルート化し、フレームワークを置き換えることを強制する以外には不可能です。たとえそれが可能だったとしても、何百ものデバイスでテストする立場にない限り、ハックが安定しているかどうかはわかりません.

とにかく、15 歳という年齢は、まだ限界に達しすぎています。特に、限界がどこにあるかを正確に判断できる人がいない場合はなおさらです。

図を正しく覚えていれば、「エッジ」は 8KB のスタック領域です。才能のあるプログラマーは、階層内のネストされたビューの数に関して「エッジ」を正確に表現できないことを認識しています。スタックの消費は、実行される操作と OS レベルによって異なるためです。

同じ問題で立ち往生している人をたくさん見てきました

「非常に多く」の価値がかなり低いです。パブリック サポート エリアで尋ねられた質問に基づくと、これは何年もの間、重大な問題ではありませんでした。

サポート ライブラリからのタブ フラグメント アクティビティは、それだけで 5 つのビューを取得します。

Android には「タブ フラグメント アクティビティ」と呼ばれるものがないため、タブの別のソースを使用することを提案する以外に、これについてはあまり役に立ちません。たとえば、ViewPagerwith TabPagerIndicator(from ViewPagerIndicator ) は、クリティカル パスに沿って 2 つのネストされたレベルの周りにある必要があります。

その場合、すべてのフラグメントは少なくとも 4 です。

才能のあるプログラマーは、フラグメントがビューを持つ必要さえないことを認識しているため、フラグメントのビューの最小数は 0 です。また、才能のあるプログラマーは、UI を持つフラグメントには 4 つではなく、少なくとも 1 つのビューが必要であることも認識しています。必要なものViewを返すonCreateView()- のセマンティクスにはonCreateView()、4 を必要とするものは何もありません。

たとえば、このサンプル プロジェクトViewPagerでは、タブにwithTabPagerIndicatorと fragment を使用しています。ルートからクリティカル パス リーフまで、全体の構造には 7 つのレベルがあります。

私の個人的なヒエラルキーに 10 個のビューがあることは特別なことではありません

はい、すべてのアクティビティに固有の 3 つのレベルを追加すると、13 のレベルが間違いなく私を緊張させ始めるためです。私の引用した例ではViewPager、そのタブとフラグメントがその上に 4 つのレベルを追加します。タブに 10 レベルの階層を持たせたいと言っている場合、アクション バー タブは 1 つの可能性ですが、それに十分なスリムなタブ ソリューションがあるとは思えません。

したがって、あなたの解決策は次のとおりです。

  • 10 レベルのタブごとの階層を簡素化する
  • それだけでは不十分な場合は、よりスリムなタブの実装を選択してください
于 2013-06-04T10:17:19.677 に答える