如何使子活动初始化或重新启动父母的活动加载器?

时间:2019-12-22 15:54:52

标签: java android

我已经制作了一个Android应用程序,该应用程序对Guardian服务器进行HTTP查询,并从其中获取JSON响应,然后显示一个列表,其中包含所有找到的文章的信息。

此列表显示在主要活动(ArticleActivity)中。该应用程序还具有订单首选项,您可以在其中选择是要按日期还是按相关性对文章进行排序。此首选项位于SettingsActivity中,后者是ArticleActivity的子级。

HTTP请求在另一个线程中发生。我已经使用了ASyncTaskLoader。

所以问题在于,在我按下SettingsActivity中的“后退”按钮以返回ArticleActivity之后,我还必须按下ArticleActivity中的“搜索”按钮来刷新列表,并在更改了orderBy参数的情况下重复查询。但这是额外的点击。当我按下SearchActivity中的“后退”按钮时,我希望我的应用以另一种顺序刷新文章列表。

该怎么做?

以下是一些代码:

ArticleActivity.java

public class ArticleActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Article>> {

    /** Adapter for the list of earthquakes */
    private ArticleAdapter mAdapter;

    /** LoaderManager for the ArticleActivity */
    private LoaderManager loaderManager;

    /** If there are no earthquakes found, this view would show up */
    private TextView mEmptyStateTextView;

    /** Circle rotating while the app is getting an HTTP response */
    private ProgressBar loadingIndicator;

    /** Default loader ID (0 — initialize loader, 1 — restart it) */
    private int loader_id = 0;

    /** By clicking these buttons you go to the previous and next 10 results */
    private Button buttonPrevious;
    private Button buttonNext;

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

        loadingIndicator = findViewById(R.id.loading_indicator);

        buttonPrevious = findViewById(R.id.button_previous);
        buttonNext = findViewById(R.id.button_next);

        Button searchButton = findViewById(R.id.search_button);
        // Set onClickListener on the searchButton
        searchButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Search field
                EditText searchText = findViewById(R.id.search_text);
                // Add a search query to the initial HTTP link
                QueryUtils.setSearchQuery(QueryUtils.getIniitialGuardianUrl() + searchText.getText().toString().replace("\\s", "+"));

                // Create an adapter with an empty list of articles
                mAdapter = new ArticleAdapter(ArticleActivity.this,
                        new ArrayList<Article>());

                // Set an adapter on the listView
                final ListView listView = findViewById(R.id.list);
                listView.setAdapter(mAdapter);

                // Set a view that would show up, if there are no
                // articles found
                mEmptyStateTextView = findViewById(R.id.empty_text_view);
                listView.setEmptyView(mEmptyStateTextView);

                // Get a reference to the ConnectivityManager to check state of network connectivity
                ConnectivityManager connMgr = (ConnectivityManager)
                        getSystemService(Context.CONNECTIVITY_SERVICE);

                // Get details on the currently active default data network
                NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();

                // If there is a network connection, fetch data
                if (networkInfo != null && networkInfo.isConnected()) {
                    // Get a reference to the LoaderManager, in order to interact with loaders.
                    loaderManager = getLoaderManager();

                    // Initialize the loader if the ID = 0. If it's 1, then restart the loader.
                    // Pass in the int ID 1 and pass in null for
                    // the bundle. Pass in this activity for the LoaderCallbacks parameter (which is valid
                    // because this activity implements the LoaderCallbacks interface).
                    if (loader_id == 0) {
                        loader_id++;
                        loaderManager.initLoader(loader_id, null, ArticleActivity.this);
                    }
                    else {
                        loaderManager.restartLoader(loader_id, null, ArticleActivity.this);
                    }

                    // Set onItemClickListener on the listView. Click on the item to
                    // read the full article
                    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            Article currentArticle = (Article) listView.getItemAtPosition(position);

                            Intent intent = new Intent(Intent.ACTION_VIEW);
                            intent.setData(Uri.parse(currentArticle.getUrl()));
                            startActivity(intent);
                        }
                    });
                }
                else {
                    // Otherwise, display error
                    // First, hide loading indicator so error message will be visible
                    View loadingIndicator = findViewById(R.id.loading_indicator);
                    loadingIndicator.setVisibility(View.GONE);

                    // Update empty state with no connection error message
                    mEmptyStateTextView.setText(getString(R.string.no_internet_connection));
                }
            }
        });


        buttonPrevious.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mAdapter.clear();

                // Assign the previous page number to the start index
                QueryUtils.setStartIndex(QueryUtils.getStartIndex() - 1);
                loaderManager.restartLoader(loader_id, null, ArticleActivity.this);
            }
        });

        buttonNext.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mAdapter.clear();

                // Assign the next page number to the start index
                QueryUtils.setStartIndex(QueryUtils.getStartIndex() + 1);
                loaderManager.restartLoader(loader_id, null, ArticleActivity.this);
            }
        });

    }

    @NonNull
    @Override
    public Loader<List<Article>> onCreateLoader(int id, @Nullable Bundle args) {
        buttonPrevious.setEnabled(false);
        buttonNext.setEnabled(false);

        // Get preferences from the default preferences location
        SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        // Get the "orderBy" preference value
        String orderBy = sharedPrefs.getString(
                getString(R.string.settings_order_by_key),
                getString(R.string.settings_order_by_default)
        );

        // If there were no articles found last time, delete "no articles found"
        // from the screen.
        mEmptyStateTextView.setText("");
        // Make loading indicator appear because the loading is about to start
        loadingIndicator.setVisibility(View.VISIBLE);
        // Create a new loader for the given URL
        return new ArticleLoader(this, QueryUtils.getSearchQuery(),
                QueryUtils.getStartIndex(), orderBy);
    }

    @Override
    public void onLoadFinished(@NonNull Loader<List<Article>> loader, List<Article> articles) {
        // Hide loading indicator because the data has been loaded
        loadingIndicator.setVisibility(View.GONE);

        // Clear the adapter of previous article data
        mAdapter.clear();

        // If there is a valid list of {@link Article}s, then add them to the adapter's
        // data set. This will trigger the ListView to update.
        if (articles != null && !articles.isEmpty()) {
            mAdapter.addAll(articles);
        }

        setPageButtonsStates();

        // Set empty state text to display "No articles found."
        if (!QueryUtils.hasResults)
            mEmptyStateTextView.setText(getString(R.string.no_articles_found));
    }

    @Override
    public void onLoaderReset(@NonNull Loader<List<Article>> loader) {
        // Loader reset, so we can clear out our existing data.
        mAdapter.clear();
    }

    private void setPageButtonsStates() {
        // Check if there are previous and next pages
        if (QueryUtils.getStartIndex() >= 2)
        {
            buttonPrevious.setEnabled(true);
        }
        else
        {
            buttonPrevious.setEnabled(false);
        }

        if (QueryUtils.getTotalArticles() - QueryUtils.getStartIndex() >= 1)
        {
            buttonNext.setEnabled(true);
        }
        else
        {
            buttonNext.setEnabled(false);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        // Go to the SettingsActivity if the settings button is clicked
        if (item.getItemId() == R.id.settings_menu)
        {
            Intent settingsIntent = new Intent(this, SettingsActivity.class);
            startActivity(settingsIntent);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

ArticleLoader.java

public class ArticleLoader extends AsyncTaskLoader<List<Article>> {

    /** Query URL */
    private String mUrl;

    /** Start index for the 10 displayed articles */
    private int startIndex;

    /** Display order preference value for the query */
    private String orderBy;

    /**
     * Constructs a new {@link ArticleLoader}.
     *
     * @param context of the activity
     * @param url to load data from
     */
    public ArticleLoader(Context context, String url,
                         int startIndex, String orderBy) {
        super(context);
        mUrl = url;
        this.startIndex = startIndex;
        this.orderBy = orderBy;
    }

    @Override
    protected void onStartLoading() {
        forceLoad();
    }

    /**
     * This is on a background thread.
     */
    @Nullable
    @Override
    public List<Article> loadInBackground() {
        if (mUrl == null) {
            return null;
        }

        // List of 10 books from Guardian's JSON response
        List<Article> currentArticles;

        mUrl = mUrl.replaceFirst("&page=1", "&page=" + startIndex);
        mUrl = mUrl.replaceFirst("&order-by=relevance", "&order-by=" + orderBy);
        // Perform the network request, parse the response, and extract a list of earthquakes.
        currentArticles = QueryUtils.fetchArticlesData(mUrl);

        return currentArticles;
    }
}

QueryUtils.java

public class QueryUtils {

    private static final String INIITIAL_GUARDIAN_URL =
            "https://content.guardianapis.com/search?api-key=6ddccecf-47d2-4a2c-99c9-77643e12a2f6&order-by=relevance&show-tags=contributor&show-elements=image&show-fields=all&page=1&q=";
    private static String searchQuery;

    // Variable for checking if there are articles found
    public static boolean hasResults;

    // Current page number
    private static int startIndex = 1;
    // Number of all the articles found
    private static int totalArticles = 0;

    public static int getTotalArticles() {
        return totalArticles;
    }

    public static int getStartIndex() {
        return startIndex;
    }

    public static void setStartIndex(int startIndex) {
        QueryUtils.startIndex = startIndex;
    }

    private QueryUtils() {
    }

    public static String getIniitialGuardianUrl() {
        return INIITIAL_GUARDIAN_URL;
    }

    public static void setSearchQuery(String searchQuery) {
        QueryUtils.searchQuery = searchQuery;
    }

    public static String getSearchQuery() {
        return searchQuery;
    }

    /**
     * Query the Guardian dataset and return an {@link ArrayList} object to represent a list of articles.
     */
    /**
     * Return a list of {@link Article} objects that has been built up from
     * parsing the given JSON response.
     */
    private static List<Article> extractArticlesFromJson(String articleJSON) {
        // If the JSON string is empty or null, then return early.
        if (TextUtils.isEmpty(articleJSON)) {
            Log.e("nojson", "No JSON returned");
            return null;
        }

        // Create an empty ArrayList that we can start adding articles to
        List<Article> articles = new ArrayList<>();

        // Try to parse the JSON response string. If there's a problem with the way the JSON
        // is formatted, a JSONException exception object will be thrown.
        // Catch the exception so the app doesn't crash, and print the error message to the logs.
        try {
            // Create a JSONObject from the JSON response string
            JSONObject jsonRoot = new JSONObject(articleJSON);
            JSONObject jsonResponse = jsonRoot.getJSONObject("response");
            Log.v("success", "JSONObject successfully created!");

            totalArticles = jsonResponse.getInt("total");
            Log.v("success", "articles found" + totalArticles);

            if (totalArticles > 0) {

                // Extract the JSONArray associated with the key called "results",
                // which represents a list of items (or articles).
                JSONArray articleArray = jsonResponse.getJSONArray("results");

                for (int i = 0; i < articleArray.length(); i++) {

                    // Get a single Article at position i within the list of articles
                    JSONObject currentArticle = articleArray.getJSONObject(i);

                    // Get an article's section name
                    String sectionName = currentArticle.getString("sectionName");

                    // Get an article's url
                    String articleUrl = currentArticle.getString("webUrl");

                    //SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MMMMM.dd GGG hh:mm aaa");
                    //String publicationDate = simpleDateFormat.format(currentArticle.getString("webPublicationDate"));

                    // Get an article's publication date
                    String publicationDate = currentArticle.getString("webPublicationDate");

                    // By default, assign "No information" to the authors' string
                    // in case there's no information about the authors of
                    // the article
                    String authorsString = "No information";

                    // For a given article, extract the JSONObject associated with the
                    // key called "tags", which represents a list of some extra information
                    // for that article, such as authors
                    JSONArray jsonAuthors = currentArticle.getJSONArray("tags");

                    if (jsonAuthors.length() > 0) {
                        // If authors are found, delete "No information" phrase
                        authorsString = "";

                        // Get an article's authors
                        for (int j = 0; j < jsonAuthors.length(); j++) {
                            JSONObject jsonAuthor = jsonAuthors.getJSONObject(j);
                            authorsString += jsonAuthor.getString("webTitle");

                            if (j != jsonAuthors.length() - 1) {
                                authorsString += "\n";
                            }
                        }
                    }

                    // For a given article, extract the JSONObject associated with the
                    // key called "fields", which represents a list of some extra information
                    // for that article, such as headline, description and thumbnail
                    JSONObject fields = currentArticle.getJSONObject("fields");

                    // Extract the value for the key called "title"
                    String headline = fields.getString("headline");
                    // Extract the value for the key called "trailText" (description of an article)
                    String description = fields.getString("trailText");
                    // An article's thumbnail link
                    String thumbnail;
                    // An article's thumbnail
                    Bitmap articleThumbnail = null;
                    if (fields.has("thumbnail")) {
                        thumbnail = fields.getString("thumbnail");
                        // Get an article thumbnail
                        articleThumbnail = getImage(thumbnail);

                        // Create a new {@link Article} object with the headline, description, section,
                        // publication date and thumbnail from the JSON response.
                        Article article = new Article(headline, description, sectionName,
                                authorsString, publicationDate, articleUrl);
                        article.setArticleThumbnail(articleThumbnail);

                        // Add the new {@link Article} to the list of articles.
                        articles.add(article);
                    }
                    else {
                        // Create a new {@link Article} object with the headline, description, section,
                        // publication date and url from the JSON response.
                        Article article = new Article(headline, description, sectionName,
                                authorsString, publicationDate, articleUrl);
                        articles.add(article);
                    }
                }
            }
        }
        catch (JSONException e) {
            // If an error is thrown when executing any of the above statements in the "try" block,
            // catch the exception here, so the app doesn't crash. Print a log message
            // with the message from the exception.
            Log.e("QueryUtils", "Problem parsing the article JSON results", e);
        }

        // Return the list of articles
        return articles;
    }

    /**
     * Get an article thumbnail.
     */
    /**
     * Return an article thumbnail
     */
    private static Bitmap getImage(String imageLink)
    {
        Bitmap image = null;

        try {
            URL url = new URL(imageLink);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            image = BitmapFactory.decodeStream(input);
        } catch (IOException e) {
            // Log exception
            Log.e("getImage: ", "Image problems", e);
        }

        return image;
    }

    /**
     * Check if there are articles found
     * @param baseJsonResponse — root JSONObject from the Guardian HTTP response
     * @return boolean value (true if there are results, false if not)
     */
    /*private static boolean hasArticlesFound(JSONObject baseJsonResponse) {
        boolean hasArticlesFound = true;

        try {
            if (baseJsonResponse.getInt("total") == 0) {
                hasArticlesFound = false;
            }
        }
        catch (JSONException e)
        {
            Log.e("hasArticlesFound: ", "JSONException", e);
        }
        return hasArticlesFound;
    }*/

    /**
     * Query the Guardian dataset and return a list of {@link Article} objects.
     */
    public static List<Article> fetchArticlesData(String requestUrl) {
        // Create URL object
        URL url = createUrl(requestUrl);

        // Perform HTTP request to the URL and receive a JSON response back
        String jsonResponse = null;
        try {
            jsonResponse = makeHttpRequest(url);
        } catch (IOException e) {
            Log.e("", "Problem making the HTTP request.", e);
        }

        // Extract relevant fields from the JSON response and create a list of {@link Article}s
        List<Article> articles =  extractArticlesFromJson(jsonResponse);

        Log.v("QueryUtils", "fetching data");

        // Return the list of {@link article}s
        return articles;
    }

    /**
     * Returns new URL object from the given string URL.
     */
    private static URL createUrl(String stringUrl) {
        URL url = null;
        try {
            url = new URL(stringUrl);
        } catch (MalformedURLException e) {
            Log.e("QueryUtils: : ", "Error with creating URL", e);
        }
        return url;
    }

    /**
     * Make an HTTP request to the given URL and return a String as the response.
     */
    private static String makeHttpRequest(URL url) throws IOException {
        String jsonResponse = "";

        // If the URL is null, then return early.
        if (url == null) {
            return jsonResponse;
        }

        HttpURLConnection urlConnection = null;
        InputStream inputStream = null;
        try {
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setReadTimeout(10000 /* milliseconds */);
            urlConnection.setConnectTimeout(15000 /* milliseconds */);
            urlConnection.setRequestMethod("GET");
            urlConnection.connect();

            // If the request was successful (response code 200),
            // then read the input stream and parse the response.
            if (urlConnection.getResponseCode() == 200) {
                inputStream = urlConnection.getInputStream();
                jsonResponse = readFromStream(inputStream);
            } else {
                Log.e("", "Error response code: " + urlConnection.getResponseCode());
            }
        } catch (IOException e) {
            Log.e("", "Problem retrieving the earthquake JSON results.", e);
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return jsonResponse;
    }

    /**
     * Convert the {@link InputStream} into a String which contains the
     * whole JSON response from the server.
     */
    private static String readFromStream(InputStream inputStream) throws IOException {
        StringBuilder output = new StringBuilder();
        if (inputStream != null) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line = reader.readLine();
            while (line != null) {
                output.append(line);
                line = reader.readLine();
            }
        }
        return output.toString();
    }
}

SettingsActivity.java

public class SettingsActivity extends AppCompatActivity {

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

    public static class SettingsFragment extends PreferenceFragment
            implements Preference.OnPreferenceChangeListener
    {
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.settings);

            // Find the "orderBy" preference and bind preference summary to value
            Preference orderBy = findPreference("order_by");
            bindPreferenceSummaryToValue(orderBy);
        }

        @Override
        public boolean onPreferenceChange(Preference preference, Object value) {
            String stringValue = value.toString();
            if (preference instanceof ListPreference) {
                ListPreference listPreference = (ListPreference) preference;
                int prefIndex = listPreference.findIndexOfValue(stringValue);
                if (prefIndex >= 0) {
                    CharSequence[] labels = listPreference.getEntries();
                    preference.setSummary(labels[prefIndex]);
                }
            } else {
                preference.setSummary(stringValue);
            }
            return true;
        }

        private void bindPreferenceSummaryToValue(Preference preference) {
            preference.setOnPreferenceChangeListener(this);
            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(preference.getContext());
            String preferenceString = preferences.getString(preference.getKey(), "");
            onPreferenceChange(preference, preferenceString);
        }
    }
}

0 个答案:

没有答案