2014-10-01 3 views
0

после this нити, я попытался сделать строку переменного состояния с этим кодом:андроид: установить видимость из AsyncTask

private int[] loadingElementIDs; 
private void initLoadingBar() { 
    final DisplayMetrics displayMetrics=getResources().getDisplayMetrics(); 
    final float screenWidthInDp = displayMetrics.widthPixels/displayMetrics.density; 
    final int elementAmount = (int) (Math.floor(screenWidthInDp * 0.5f/30) * 5); 

    //set margins 
    LinearLayout container = (LinearLayout)findViewById(R.id.loading_outer); 
    ... 
    container.requestLayout(); 

    //declare length 
    loadingElementIDs = new int[elementAmount]; 

    LayoutParams LLParams = new LayoutParams(0, LayoutParams.MATCH_PARENT); 
    LLParams.weight = 1f; 
    LinearLayout element; 
    for (int i=0; i<elementAmount; i++) { 
     int id = generateViewId(); //creates unique id 

     element = new LinearLayout(this); 
     element.setVisibility(View.INVISIBLE); 
     element.setLayoutParams(LLParams); 
     element.setBackgroundDrawable(getResources().getDrawable(R.drawable.loading_inner)); 
     element.setId(id); 
     element.requestLayout();    
     container.addView(element); 

     loadingElementIDs[i] = id; 
    } 

} 

это работает хорошо для меня, но теперь я хочу, чтобы вычислить н с AsyncTask и сделать код видимым (код в пределах моего класса деятельности):

private class PrefetchData extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 

    @SuppressWarnings("static-access") 
    @Override 
    protected Void doInBackground(Void... arg0) { 

     try { 
      int step = 0; 
      float totalSteps = 100f; 
      while (...) { 
       step++; 

       // ................... 

       //show status 
       setLoadingStatus(step/totalSteps); 
      }    
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 


    @Override 
    protected void onPostExecute(Void result) { 
     super.onPostExecute(result); 
     Intent i = new Intent(SplashScreen.this, MainActivity.class); 
     startActivity(i); 
     finish(); 
    } 

} 

public void setLoadingStatus(float percentage) { 
    int max = (int) Math.min(Math.floor(percentage * loadingElementIDs.length), 
    for (int d=0; d<max; d++) { 
     ((LinearLayout)findViewById(loadingElementIDs[d])).setVisibility(View.VISIBLE); 
     LinearLayout el = (LinearLayout)this.findViewById(loadingElementIDs[d]); 
     el.setVisibility(LinearLayout.VISIBLE); 
    } 
} 

И это не работает. если я звоню setLoadingStatus(20f); из onCreate, он работает отлично, но не в AsyncTask. Конечно, я начинаю initLoadingBar(); и new PrefetchData().execute(); в действиях onCreate().

Знаете ли вы, что я делаю неправильно?

+2

Не может вызывать функции пользовательского интерфейса от doInBackground(), это отдельный поток (то есть всей цель AsnycTasks). Вам нужно сделать это в onProgressUpdate() или onPostExecute() – zgc7009

ответ

0

спасибо вам, ребята, я решил его с onProgressUpdate. вместо setLoadingStatus я называю это:

private class PrefetchData extends AsyncTask<Void, Float, Void> { 
    .... 
    protected void onProgressUpdate(Float... values) { 
     for (int d=0; d<Math.min(Math.floor(values[0] * loadingElementIDs.length), loadingElementIDs.length); d++) { 
      LinearLayout el = (LinearLayout)findViewById(loadingElementIDs[d]); 
      el.setVisibility(LinearLayout.VISIBLE); 
     } 
    } 
} 
1

Я не знаю, как это был объединен, комментарий все BORKED, но запрашиваемый фрагмент кода ниже для управления этим с обработчиком:

определить обработчик в вашей деятельности:

Handler handler = new Handler(){ 

    handleMessage(Message msg) 
    { 
     if (msg.what == STATUS) 
     { 
      //do something if it's a message form your AsyncTask 
     } 
     else 
     //other messages.. 
    } 

}; 

при создании вашей AsyncTask, дайте ему ваш обработчик. определить конструктор, чтобы принять это и сохранить локальную ссылку на него.

new PrefetchData(handler).execute(...); 

, а затем внутри AsyncTask: (STATUS будет постоянной установки в качестве кода сообщения ..)

while (...) { 
      step++; 

      // ................... 

      //show status 
      handler.obtainMessage(STATUS, step/totalSteps).sendToTarget(); 
     } 
+0

У вас есть пример, как я мог бы решить его с помощью обработчиков (в AsyncTask?) – vtni

1

Использование UI нить для компонентов обновления пользовательского интерфейса. Если вам необходимо обновить задачу, вы можете использовать publishProgress (xxx) и onProgressUpdate (xxx). Для более dateils: http://developer.android.com/reference/android/os/AsyncTask.html

0

Вы можете runOnUiThread метод для вызова функции Ui из любого thread

runOnUiThread(new Runnable() { 
    public void run() { 
     // some code #3 (Write your code here to run in UI thread) 
    } 
}); // enter code here 
+0

Я не могу использовать Runnable, потому что мне нужно 'onPostExecute' – vtni

Смежные вопросы