2017-07-26 77 views
1

我有一個包含兩個選項的菜單。其中一個選項用網頁內容刷新應用程序的內容。我想調暗屏幕上的ListView,然後顯示進度條,直到內容刷新。我有方法startLoadingAnimation()endLoadingAnimation()完成此操作。但是當我在他們之間撥打refreshArticles()時,他們停止工作。我在他們的打印語句顯示他們應該執行時,但是當Android - 使用AsyncTask調用方法會中斷其他方法

case R.id.refresh: 
    startLoadingAnimation(); 
    refreshArticles(); 
    endLoadingAnimation(); 

執行,只有打印語句通過,而不是UI更改。

全部活動代碼:

package com.bruno.newsreader; 

import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.SharedPreferences; 
import android.database.Cursor; 
import android.database.sqlite.SQLiteDatabase; 
import android.os.AsyncTask; 
import android.support.v7.app.AlertDialog; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuInflater; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.AdapterView; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 
import android.widget.NumberPicker; 
import android.widget.ProgressBar; 

import org.json.JSONArray; 
import org.json.JSONException; 
import org.json.JSONObject; 

import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.HttpURLConnection; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 

public class ListActivity extends AppCompatActivity { 

    private ListView listView; 
    private int numArticles; 
    private SharedPreferences sharedPreferences; 
    private ArrayList<String> articleTitles; 
    private ArrayList<String> articleUrls; 
    private SQLiteDatabase articleDB; 
    private ProgressBar progressBar; 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 

     MenuInflater menuInflater = getMenuInflater(); 
     menuInflater.inflate(R.menu.options_menu, menu); 

     return super.onCreateOptionsMenu(menu); 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     super.onOptionsItemSelected(item); 

     switch (item.getItemId()) { 
      case R.id.refresh: 
       startLoadingAnimation(); 
       refreshArticles(); 
       endLoadingAnimation(); 
       return true; 
      case R.id.numArticles: 
       final NumberPicker numberPicker = new NumberPicker(getApplicationContext()); 
       numberPicker.setMaxValue(50); 
       numberPicker.setMinValue(5); 
       numberPicker.setValue(numArticles); 
       new AlertDialog.Builder(this) 
         .setTitle("Set Number of Articles") 
         .setMessage("This will determine how many articles are stored on your device:") 
         .setView(numberPicker) 
         .setPositiveButton("OK", new DialogInterface.OnClickListener() { 

          @Override 
          public void onClick(DialogInterface dialog, int which) { 
           numArticles = numberPicker.getValue(); 
           sharedPreferences.edit().putInt("numArticles", numArticles).apply(); 
          } 
         }) 
         .setNegativeButton("Cancel", null) 
         .show(); 
      default: 
       return false; 

     } 
    } 

    public class TopArticleDownloadTask extends AsyncTask<URL, Void, JSONArray> { 

     @Override 
     protected JSONArray doInBackground(URL... urls) { 
      String jsonString = ""; 
      URL url = urls[0]; 
      HttpURLConnection urlConnection = null; 
      try { 
       urlConnection = (HttpURLConnection) url.openConnection(); 
       InputStream in = urlConnection.getInputStream(); 
       InputStreamReader reader = new InputStreamReader(in); 
       int data = reader.read(); 
       while(data != -1) { 
        char current = (char) data; 
        jsonString += current; 
        data = reader.read(); 
       } 
       return new JSONArray(jsonString); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       return null; 
      } 
     } 
    } 

    public class IndividualArticleDownloadTask extends AsyncTask<URL, Void, JSONObject> { 

     @Override 
     protected JSONObject doInBackground(URL... urls) { 
      String jsonString = ""; 
      URL url = urls[0]; 
      HttpURLConnection urlConnection = null; 
      try { 
       urlConnection = (HttpURLConnection) url.openConnection(); 
       InputStream in = urlConnection.getInputStream(); 
       InputStreamReader reader = new InputStreamReader(in); 
       int data = reader.read(); 
       while(data != -1) { 
        char current = (char) data; 
        jsonString += current; 
        data = reader.read(); 
       } 
       return new JSONObject(jsonString); 
      } catch (Exception e) { 

      } 
      return null; 
     } 
    } 

    private void refreshArticles() { 

     String topArticlesUrlString = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty"; 
     URL topArticlesUrl = null; 
     try { 
      topArticlesUrl = new URL(topArticlesUrlString); 
     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } 
     TopArticleDownloadTask topArticleDownloadTask = new TopArticleDownloadTask(); 
     JSONArray topArticlesJSON = null; 
     try { 
      topArticlesJSON = topArticleDownloadTask.execute(topArticlesUrl).get(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     int[] articleIds = new int[numArticles]; 
     for (int i = 0; i < articleIds.length; i++) { 
      try { 
       articleIds[i] = topArticlesJSON.getInt(i); 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
     } 

     String articleUrlStart = " https://hacker-news.firebaseio.com/v0/item/"; 
     String articleUrlEnd = ".json?print=pretty"; 
     articleDB.execSQL("DELETE FROM articles"); 
     for (int id : articleIds) { 
      String articleUrlString = articleUrlStart + id + articleUrlEnd; 
      URL articleUrl = null; 
      try { 
       articleUrl = new URL(articleUrlString); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } 
      JSONObject articleJSON = null; 
      try { 
       IndividualArticleDownloadTask individualArticleDownloadTask = new IndividualArticleDownloadTask(); 
       articleJSON = individualArticleDownloadTask.execute(articleUrl).get(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 

      try { 
       String title = articleJSON.getString("title"); 
       title = title.replaceAll("'", "''"); 
       String url = articleJSON.getString("url"); 
       articleDB.execSQL("INSERT INTO articles (title, url) VALUES ('" + title + "', '" + url + "')"); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 

     syncArrayListsWithDB(); 
    } 

    private void syncArrayListsWithDB() { 
     articleTitles.clear(); 
     articleUrls.clear(); 

     Cursor cursor = articleDB.rawQuery("SELECT * FROM articles", null); 

     if (cursor.moveToFirst()) { 
      while(!cursor.isAfterLast()) { 
       String title = cursor.getString(0); 
       String url = cursor.getString(1); 
       articleTitles.add(title); 
       articleUrls.add(url); 
       cursor.moveToNext(); 
      } 
     } 

     ArrayAdapter<String> arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, articleTitles); 
     listView.setAdapter(arrayAdapter); 
    } 

    private void startLoadingAnimation() { 
     System.out.println("start start load"); 
     listView.setAlpha(.25f); 
     progressBar.setVisibility(View.VISIBLE); 
     System.out.println("end start load"); 
    } 

    private void endLoadingAnimation() { 
     System.out.println("start end load"); 
     listView.setAlpha(1); 
     progressBar.setVisibility(View.INVISIBLE); 
     System.out.println("end end load"); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_list); 

     articleTitles = new ArrayList<>(); 
     articleUrls = new ArrayList<>(); 
     listView = (ListView) findViewById(R.id.listView); 
     progressBar = (ProgressBar) findViewById(R.id.progressBar); 

     sharedPreferences = this.getSharedPreferences("com.bruno.newsreader", Context.MODE_PRIVATE); 
     numArticles = sharedPreferences.getInt("numArticles", 10); 

     articleDB = this.openOrCreateDatabase("Data", MODE_PRIVATE, null); 

     articleDB.execSQL("CREATE TABLE IF NOT EXISTS articles (title VARCHAR, url VARCHAR)"); 

     Cursor c = articleDB.rawQuery("SELECT count(*) FROM articles", null); 
     c.moveToFirst(); 
     int count = c.getInt(0); 
     if (count == 0) { 
      refreshArticles(); 
     } else { 
      syncArrayListsWithDB(); 
     } 

     listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

      @Override 
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
       Intent intent = new Intent(getApplicationContext(), ReaderActivity.class); 
       intent.putExtra("url", articleUrls.get(position)); 
       startActivity(intent); 
      } 
     }); 
    } 
} 

回答

0

很難確切說出refreshArticles()究竟是幹什麼的,但我懷疑,答案是「大量的工作」,並認爲它沒有這樣做異步(即,它只是在執行工作而不是產生一個新線程來完成它,然後在完成時給你回電)。

onOptionsItemSelected()在主線程(也稱爲UI線程)上執行。在主線程正在進行任何操作時,UI無法更新。因此,如果您正在「開始」加載動畫,執行大量工作,然後「停止」該動畫(全部位於主線程中),那麼您將不會看到動畫運行。當您在主線程上完成代碼的運行時,您已停止加載動畫。

解決方法是將refreshArticles()所做的工作移動到後臺線程。有很多不同的方法來完成這一點;閱讀約Handler.post(Runnable)AsyncTask應該讓你開始。

+0

謝謝!我將我的工作移到了一個新的'AsyncTask',它在'onPreExecute()'和'onPostExecute(Result result)'方法中調用了兩個動​​畫方法。現在起作用了。 –

相關問題