2017-07-26 60 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)'方法中调用了两个动​​画方法。现在起作用了。 –

相关问题