Как получить данные с двух или более сайтов одновременно? (Приложение для Android) - PullRequest
3 голосов
/ 07 мая 2019

Я создал приложение, которое получает данные с разных URL. Я использовал цикл for для получения данных из разных URL-адресов с помощью jsoup lib. Теперь это занимает много времени, как 5 сек. Сначала получите данные из url1, затем из 2, а затем из 3 .. Это то, что занимает время, я думаю.

Итак, я хочу знать, можем ли мы получать данные из разных URL-адресов одновременно (из нескольких потоков) или нет?

public  class Title extends AsyncTask <String, Void, Void> {

    String url,ver;
    Bitmap mIcon11 = null;
    ArrayList<App> appsList = new ArrayList<>();

    @Override
    protected Void doInBackground(String ... strings) {
        try {

            for (String string : strings) {
                Document document = Jsoup.connect(string).get();

                Elements a = document.select("div.AppCont");
                Elements b = a.select("article");
                Elements c = b.select("div.ImgDiv");
                Elements d = c.select("img");
                url = d.attr("src");

                InputStream in = new URL(url).openStream();
                mIcon11 = BitmapFactory.decodeStream(in);

                ver = b.get(0).text();
                String z = string.replace("https://a2zapk.com/History/", "");
                z = z.replace("/", "");

                PackageInfo pi = getApplicationContext().getPackageManager().getPackageInfo((z), PackageManager.GET_META_DATA);
                String versionName = pi.versionName;

                ver = ver + " (Installed Version: " +versionName + ")";
                appsList.add(new App(ver, mIcon11));

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
         add(appsList);
    }

1 Ответ

2 голосов
/ 07 мая 2019

Вы можете это сделать, но управление потоками для этих задач может оказаться сложным. Я бы рекомендовал использовать Rxava , чтобы подготовить отдельную наблюдаемую информацию для каждого сайта, с которого вы хотите получать данные. Затем используйте merge или mergeDelayError , чтобы объединить результаты в один Observable, на который вы можете подписаться в главном потоке для обновления вашего пользовательского интерфейса.

Проверьте RxJavaAndroid для получения помощи в подписке на эти обновления в главном потоке Android.

Вам захочется ознакомиться с 4 основными частями RxJava:

  1. Что вы делаете - в вашем случае это выборка данных с сервера
  2. Какой пул потоков выполняет эту задачу - я бы порекомендовал Schedulers.io (), который является пулом, выделенным специально для задач ввода-вывода, таких как выборка данных.
  3. В каком пуле потоков вы будете наблюдать результаты - AndroidSchedulers.mainThread () - то, что вам нужно здесь
  4. Что делать с результатами - обновить какой-либо пользовательский интерфейс и т. Д.

Это выглядело бы примерно следующим образом при использовании RxJava (в Kotlin)

// What you're doing
Observable.fromCallable {
    listOfApps = parseAppsList(Jsoup.connect("server1.host.com"))
    return@fromCallable listOfApps
}
        // Where you're doing it
        .subscribeOn(Schedulers.io())
        // Where you're observing results
        .observeOn(AndroidSchedulers.mainThread())
        // What you're doing with those results
        .subscribe({ apps ->
            appsList.addAll(apps)
        }, { exception -> 
            // Show an error message
        })

Чтобы получить несколько результатов одновременно и добавить их по завершении, ваш код будет выглядеть примерно так:

val fromServer1 = Observable.fromCallable {
    listOfApps = parseAppsList(Jsoup.connect("server1.host.com"))
    return@fromCallable listOfApps
}
        .subscribeOn(Schedulers.io())


val fromServer2 = Observable.fromCallable {
    listOfApps = parseAppsList(Jsoup.connect("server2.host.com"))
    return@fromCallable listOfApps
}
        .subscribeOn(Schedulers.io())


Observable.merge(fromServer1, fromServer2)
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({ apps ->
            // Note that this callback will be called once per server
            appsList.addAll(apps)
        }, { exception ->
            // Show an error message
        })
...