<commit_before>package com.tpb.hn.story;

import android.util.Log;

import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONObjectRequestListener;
import com.tpb.hn.network.APIPaths;

import org.json.JSONObject;

import java.util.HashMap;

/**
 * Created by theo on 19/10/16.
 * http://stackoverflow.com/questions/6053602/what-arguments-are-passed-into-asynctaskarg1-arg2-arg3
 */

public class ReadabilityLoader {
    private static final String TAG = ReadabilityLoader.class.getCanonicalName();
    private static HashMap<String, JSONObject> cache = new HashMap<>();
    private ReadabilityLoadDone listener;

    public ReadabilityLoader(ReadabilityLoadDone listener) {
        this.listener = listener;
    }

    void loadArticle(final String url) {
        if(cache.containsKey(url)) {
            listener.loadDone(cache.get(url), true);
        }
        final long start = System.nanoTime();
        AndroidNetworking.get(APIPaths.getReadabilityParserPath(url))
                .setTag("readability")
                .setPriority(Priority.HIGH)
                .build()
                .getAsJSONObject(new JSONObjectRequestListener() {
                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            Log.d(TAG, "onResponse: " + (System.nanoTime()-start)/1E9);
                            listener.loadDone(response, response != null);
                            if(response != null) {
                                cache.put(url, response);
                            }
                        } catch(Exception e) {
                            Log.e(TAG, "onResponse: ", e);
                        }
                    }

                    @Override
                    public void onError(ANError anError) {
                        Log.e(TAG, "onError: ", anError );
                    }
                });
    }

    private void stripImageCopyright() {}

    public interface ReadabilityLoadDone {

        void loadDone(JSONObject result, boolean success);

    }

}<commit_msg>Added better caching to the ReadabilityLoader. Listeners are added to a static  HashMap, and the GET is only called if the HashMap is empty. When getAsJSONObject is called, it updates all of the listeners. This means that any GET calls for a URL which is already being loaded will all return from the same GET.<commit_after>package com.tpb.hn.story;

import android.util.Log;

import com.androidnetworking.AndroidNetworking;
import com.androidnetworking.common.Priority;
import com.androidnetworking.error.ANError;
import com.androidnetworking.interfaces.JSONObjectRequestListener;
import com.tpb.hn.network.APIPaths;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Created by theo on 19/10/16.
 * http://stackoverflow.com/questions/6053602/what-arguments-are-passed-into-asynctaskarg1-arg2-arg3
 */

public class ReadabilityLoader {
    private static final String TAG = ReadabilityLoader.class.getCanonicalName();
    private static HashMap<String, JSONObject> cache = new HashMap<>();
    private static HashMap<String, ArrayList<ReadabilityLoadDone>> listenerCache = new HashMap<>();
    private ReadabilityLoadDone listener;

    public ReadabilityLoader(ReadabilityLoadDone listener) {
        this.listener = listener;
    }

    void loadArticle(final String url) {
        if(cache.containsKey(url)) {
            listener.loadDone(cache.get(url), true);
        }
        if(listenerCache.containsKey(url)) {
            listenerCache.get(url).add(listener);
        } else {
            final ArrayList<ReadabilityLoadDone> listeners = new ArrayList<>();
            listeners.add(listener);
            listenerCache.put(url, listeners);
            final long start = System.nanoTime();
            AndroidNetworking.get(APIPaths.getReadabilityParserPath(url))
                    .setTag("readability")
                    .setPriority(Priority.HIGH)
                    .build()
                    .getAsJSONObject(new JSONObjectRequestListener() {
                        @Override
                        public void onResponse(JSONObject response) {
                            try {
                                Log.d(TAG, "onResponse: " + (System.nanoTime()-start)/1E9);
                                Log.i(TAG, "onResponse: updating " + listenerCache.get(url).size() + " listeners");
                                for(ReadabilityLoadDone rld : listenerCache.get(url)) {
                                    rld.loadDone(response, response != null);
                                }
                                listenerCache.remove(url);
                                if(response != null) {
                                    cache.put(url, response);
                                }
                            } catch(Exception e) {
                                Log.e(TAG, "onResponse: ", e);
                            }
                        }

                        @Override
                        public void onError(ANError anError) {
                            Log.e(TAG, "onError: ", anError );
                        }
                    });
        }

    }

    private void stripImageCopyright() {}

    public interface ReadabilityLoadDone {

        void loadDone(JSONObject result, boolean success);

    }

}
{'fraction_non_alphanumeric': 0.09191043698085952, 'fraction_numerical': 0.0065005417118093175, 'mean_word_length': 1.7736604907361042, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5709672', 'n_tokens_mistral': 1419, 'n_tokens_neox': 1350, 'n_words': 293}