JSONArray无法立即更新

时间:2018-07-11 06:10:15

标签: android android-asynctask

每当在我的Popular Movies Udacity项目中,我都会在收藏夹电影收藏集中的电影海报上单击,该收藏夹电影已脱机维护为数据库,URL列表会正确更新,但AsyncTask中创建的JSONArray不会立即更新。 / p>

package com.example.android.popularmovies;

import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.example.android.popularmovies.Database.Contract;
import com.example.android.popularmovies.utilities.NetworkUtils;
import com.facebook.stetho.Stetho;

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

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    private final static String BASE_POSTER_URL = "http://image.tmdb.org/t/p/w500/";
    private static String OPTION = "OPTION";

    TextView mNoFavorites;
    // = new JSONArray();
    JSONArray favoriteJsonArray;
    int optionChosen;

    private ProgressBar mProgessBar;
    private TextView mErrorMessage;
    private Button mRetry;
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private URL url;
    private ArrayList<String> posterList;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null)
            optionChosen = savedInstanceState.getInt(OPTION);
        Stetho.initializeWithDefaults(this);
        setContentView(R.layout.activity_main);
        mRecyclerView = findViewById(R.id.my_recycler_view);
        mRecyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
        mRecyclerView.setLayoutManager(mLayoutManager);
        //mAdapter = new MainActivityAdapter(this, posterList, null);
        //mRecyclerView.setAdapter(mAdapter);
        mProgessBar = findViewById(R.id.progess_bar);
        mErrorMessage = findViewById(R.id.error_message);
        mRetry = findViewById(R.id.retry);
        mNoFavorites = findViewById(R.id.no_favorites_yet);
        favoriteJsonArray = new JSONArray();
        tryToConnect(new View(this));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.preferences, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        try {
            if (item.getItemId() == R.id.top_rated) {
                mRecyclerView.setVisibility(View.VISIBLE);
                mNoFavorites.setVisibility(View.INVISIBLE);
                url = NetworkUtils.buildUrl("top_rated");
                if (url != null) {
                    mErrorMessage.setVisibility(View.INVISIBLE);
                    mRetry.setVisibility(View.INVISIBLE);
                    new FetchMovies().execute(url, null, null);
                }
                optionChosen = 1;
            }
            if (item.getItemId() == R.id.most_popular) {
                mRecyclerView.setVisibility(View.VISIBLE);
                mNoFavorites.setVisibility(View.INVISIBLE);
                url = NetworkUtils.buildUrl("most_popular");
                if (url != null) {
                    mErrorMessage.setVisibility(View.INVISIBLE);
                    mRetry.setVisibility(View.INVISIBLE);
                    new FetchMovies().execute(url, null, null);
                }
                optionChosen = 2;
            }
            if (item.getItemId() == R.id.favorites) {
                optionFavorites();
                optionChosen = 3;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (java.lang.NullPointerException e) {
            e.printStackTrace();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (optionChosen == 3)
            optionFavorites();
    }


    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save the user's current game state
        savedInstanceState.putInt(OPTION, optionChosen);


        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);
    }

    /*  public void onRestoreInstanceState(Bundle savedInstanceState) {
          // Always call the superclass so it can restore the view hierarchy
          super.onRestoreInstanceState(savedInstanceState);

          // Restore state members from saved instance
          optionChosen = savedInstanceState.getInt(OPTION);

      }
  */
    private void optionFavorites() {
        try {
            String[] projection = {"movie_id", "favorite_poster_path"};
            Cursor cursor = getContentResolver().query(
                    Contract.FavoriteMovieDatabase.CONTENT_URI,
                    projection,
                    null,
                    null,
                    null
            );
            ArrayList<String> posterPathArrayList = new ArrayList<>();
            ArrayList<URL> urlArrayList = new ArrayList<>();

            if (cursor != null && cursor.moveToFirst()) {
                do {
                    String posterPath = cursor.getString(cursor.getColumnIndex(Contract.FavoriteMovieDatabase.FAVORITE_POSTER_PATH));
                    posterPathArrayList.add(BASE_POSTER_URL + posterPath);
                    int movieId = cursor.getInt(cursor.getColumnIndex("movie_id"));
                    URL favoriteURL = NetworkUtils.buildUrl("favorites", movieId);
                    urlArrayList.add(favoriteURL);
                } while (cursor.moveToNext());
                Log.d("urllist", "" + urlArrayList.toString());
                new FetchFavorites().execute(urlArrayList, null, null);
                mAdapter = new MainActivityAdapter(MainActivity.this, posterPathArrayList, favoriteJsonArray);
                mRecyclerView.setAdapter(mAdapter);
            } else {
                mRecyclerView.setVisibility(View.INVISIBLE);
                mNoFavorites.setVisibility(View.VISIBLE);
            }
        } catch (java.lang.NullPointerException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    private void noConnection() {
        mErrorMessage.setText(R.string.no_connection);
        mErrorMessage.setVisibility(View.VISIBLE);
        mRetry.setText(R.string.retry);
        mRetry.setVisibility(View.VISIBLE);
    }

    public void tryToConnect(View v) {
        try {
            url = NetworkUtils.buildUrl("most_popular");
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        if (url != null) {
            mErrorMessage.setVisibility(View.INVISIBLE);
            mRetry.setVisibility(View.INVISIBLE);
            new FetchMovies().execute(url, null, null);
        }
    }


    private class FetchMovies extends AsyncTask<URL, Void, String> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgessBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected String doInBackground(URL... params) {
            URL searchUrl = params[0];
            String searchResults = null;
            try {
                searchResults = NetworkUtils.getResponseFromHttpUrl(searchUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return searchResults;
        }

        @Override
        protected void onPostExecute(String searchResults) {
            mProgessBar.setVisibility(View.INVISIBLE);
            try {
                posterList = new ArrayList<>();
                if (searchResults != null && !searchResults.equals("")) {
                    JSONObject jsonObject = new JSONObject(searchResults);
                    JSONArray pageOne = jsonObject.getJSONArray("results");
                    int length = pageOne.length();
                    for (int i = 0; i < length; i++) {
                        JSONObject result = pageOne.getJSONObject(i);
                        String posterPath = BASE_POSTER_URL + result.getString("poster_path");
                        posterList.add(posterPath);
                    }
                    mAdapter = new MainActivityAdapter(MainActivity.this, posterList, pageOne);
                    mRecyclerView.setAdapter(mAdapter);
                } else noConnection();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private class FetchFavorites extends AsyncTask<ArrayList<URL>, Void, ArrayList<String>> {


        @Override
        protected ArrayList<String> doInBackground(ArrayList<URL>... params) {
            ArrayList<URL> urlArrayList = params[0];
            ArrayList<String> stringArrayList = new ArrayList<>();
            String searchResults;
            URL searchUrl;
            favoriteJsonArray = new JSONArray();
            for (int i = 0; i < urlArrayList.size(); i++)
                try {
                    searchUrl = urlArrayList.get(i);
                    searchResults = NetworkUtils.getResponseFromHttpUrl(searchUrl);
                    stringArrayList.add(searchResults);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            return stringArrayList;
        }

        @Override
        protected void onPostExecute(ArrayList<String> stringArrayList) {
            for (int i = 0; i < stringArrayList.size(); i++)
                try {
                    favoriteJsonArray.put(new JSONObject(stringArrayList.get(i)));
                } catch (JSONException e) {
                    e.printStackTrace();
                }
        }
    }
}
当数据库发生更改时,

urlArrayList可以正确更新,但是AsyncTask内部更新的favoriteJsonArray却没有。为什么?

1 个答案:

答案 0 :(得分:0)

您的代码中有两个问题:

  1. ,在FetchFavorites.doInBackground()中,您为new JSONArray()分配了favoriteJsonArray,但是您的mAdapter仍然保留着旧的引用,即一个空的JSONArray。

  2. 您在更新mAdapter.notifyDataSetChanged()之后没有致电favoriteJsonArray

您可以通过以下方式解决问题:

  1. 不要在{{1}中使用new JSONArray(),并在更新FetchFavorites.doInBackground()之后调用mAdapter.notifyDataSetChanged(),但是仍然存在问题,您应该清除{{1 }}每次获取新数据并清除favoriteJsonArray都是一种无聊的工作(没有favoriteJsonArray方法)。

  2. JSONArray,但是编辑您的clear(),添加类似new JSONArray()的方法,并为其设置新创建的MainActivityAdapter,然后调用setFavorites(JSONArray array)