2017-06-12 19 views
1

私はstackoverflowとそれに類するすべての回答を行ってきましたが、使用していないことが判明しました。Androidスレッドで画像を変更する

誰もこの機能が動作していない理由を指摘できますか?それは簡単でなければなりません:イメージを6秒ごとに更新します(3分ごとにテストされますが、6秒とします)。

コードが行うことは、4つの画像のそれぞれを段階的に通過しますが、画像は変更されません。しかし、最後の画像になると、それは変わります(??)。

質問:

  1. これで何が悪いのでしょうか?
  2. なぜ最後の画像のみを更新するのですか?
  3. "postDelayed"ではなく、ハンドラーの "post"だけでコードを開始すると、タブレットは黒い画面のままです。なぜ私はそれを動作させるために遅れてコードを開始する必要がありますか?

int currentIndex = 0; 
boolean start = false; 
ImageView descriptionImage; 
private Runnable timerRunnable; 
long startTime = 0; 
private Handler handler; 

int[] pictureIds = new int[]{R.drawable.hang, R.drawable.dog, R.drawable.coffee, R.drawable.about}; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    pictureDescription = new ArrayList<String>(); 
    handler = new Handler(Looper.getMainLooper()); 
} 

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View v = inflater.inflate(R.layout.fragment_picture_test, container, false); 
    descriptionImage = (ImageView) v.findViewById(R.id.iv_picture); 

    return v; 
} 

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    start(); 
} 

private void start() { 

    start = true; 
    startTime = System.currentTimeMillis(); 
    loadImage(); 
    timerRunnable = new Runnable() { 

     @Override 
     public void run() { 
      while (start) { 
       long time = System.currentTimeMillis() - startTime; 
       float mins = (float) time/(60 * 1000); 
       if (mins >= 0.1f) { 
        startTime = System.currentTimeMillis(); 
        if (currentIndex < pictureIds.length) { 
         currentIndex++; 
         loadImage(); 
        } 
       } 
      } 
     } 
    }; 
    handler.postDelayed(timerRunnable, 1000); 
} 

private void loadImage() { 
    getActivity().runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      if (currentIndex < pictureIds.length) { 
       descriptionImage.setImageResource(pictureIds[currentIndex]); 
      } else { 
       start = false; // finish 
      } 

     } 
    }); 
} 

ありがとう!

EDIT:ハンドラの代わりにimageviewスレッドに投稿しても機能しません。

descriptionImage.postDelayed(timerRunnable、1000);

+0

このコードでは、while(start)ループでUIスレッドをハングアップしませんか? –

+0

これらの2つの回答に加えて、あなたのフラグメントの 'onPause'でHandler#removeCallbackを呼び出すことを忘れないでください。 –

+0

そして、' runOnUiThread(action) 'は' uiHandler 'と同等です。投稿(アクション); '。あなたは既にUIハンドラを持っているので、なぜ 'getActivity()。runOnUiThread()'? –

答えて

2

この問題は何ですか?

UIスレッドが真となったために、あなたの条件に(if (mins >= 0.1f) {を)待って、(while (start))ビジー状態である一方で、それは(図のように)残りの世話をすることはできません。

Why would it only update the last image? 

if (currentIndex < pictureIds.length) {が真でない場合にのみ、それが描くことができますので、startが偽になり、私が代わりにハンドラに単に「ポスト」でコードを起動すると、UIスレッドが最終的に

を描くことができます "postDelayed" - タブレットは黒い画面のままです。なぜ私は を動作させるために遅れてコードを開始する必要がありますか?

あなたは3秒ごとに自分の画像を変更したい場合、あなたはハンドラ#postDelayedを使用して保つことができるポイント1.

を参照してください。例えば。

start = true; 
startTime = System.currentTimeMillis(); 
loadImage(); 
timerRunnable = new Runnable() { 

    @Override 
    public void run() { 
     currentIndex = currentIndex++ % pictureIds.length; 
     loadImage(); 
     handler.postDelayed(this, 3000); 
    } 
}; 
handler.postDelayed(timerRunnable, 3000); 
+0

これは完全に意味をなさない!私は不義です。だから私はこれを新しいスレッド上で動作させたい場合は、それを実行するHandlerThreadを作成します。そして、UIの変更をgetActivity.runOnUIThreadにポストしますか? – LifeQuestioner

+1

通常の 'Thread'で十分でしょう。 Btw、私はどんな種類の[busy waiting](https://en.wikipedia.org/wiki/Busy_waiting)メカニズムを避けるだろう – Blackbelt

2

問題は、whileループがメインスレッドで実行されていることです。つまり、whileループが終了するまでUIが更新されることはありません(最終的なイメージのみを見る理由)。 start関数として試してみてください:

private void start() { 

    timerRunnable = new Runnable() { 

     @Override 
     public void run() { 
      if (currentIndex < pictureIds.length) { 
       loadImage(); 
       currentIndex++; 
       handler.postDelayed(timerRunnable, 6 * 1000); 
      } 
     } 
    }; 
    handler.post(timerRunnable); 
} 
+0

これは完全に意味をなさない!私は不義です。だから私はこれを新しいスレッド上で動作させたい場合は、それを実行するHandlerThreadを作成します。そして、UIの変更をgetActivity.runOnUIThreadにポストしますか? – LifeQuestioner

+0

機能的には、はい、あなたは新しい 'Thread'を使うことができ、UIは保持されません。しかし、あなたの場合、あなたがやっていることはすべてUI上にあるので、スレッド間の切り替えは不要です。 'handler.postDelayed'関数を使うことは、バックグラウンドスレッドでwhileループを連続して実行するよりもはるかに優れています(他の答えに記載されている" busy waiting "メカニズム)。 – Adam

関連する問題