複数のgetリクエストを順に処理する

※2022/08/30更新

複数のgetリクエストを連続して実行する場合、非同期的に実行するとコールバックにばらばらに帰ってきてしまう。

getリクエストの結果を受け取った後に、次のリクエストを実行するようなロジックを探す必要があった。

node-fetchを活用して、下記のようなソースで実行すればよい。
www.npmjs.com

 

//index.js
import fetch from 'node-fetch';


const urls = [""/*1つめのURL*/, ""/*2つめのURL*/];

for(const url of urls) {
    const response = await fetch(url);
    const body = await response.text();
    console.log(body.length);
}
//package.json
{
  "name": "fetch-sample",
  "type": "module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-fetch": "^3.2.10"
  }
}

【Android】 WebViewで特定の位置にスクロールする

WebViewClientのonPageFinished()で、スクロール位置をセットすればよいのかと思いきや、動かなかったのでメモ

 

@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//時間をずらしてスクロールさせないと動かない
//100msecずらしている
view.postDelayed(new Runnable() {
@Override
public void run() {
webView.setScrollX(
/*スクロールさせたいX座標*/);
webView.setScrollY(/*スクロールさせたいY座標*/);
       }
   }, 100);

}

少しタイミングをずらすことで、スクロールできましたとさ

【Android】WebViewのloadData()

loadData()を使うと、何故かこいつを2回呼び出さないとページ遷移が起こらないことがあった。

調べると

stackoverflow.com

Avoid WebView#loadData(String data, String mimeType, String encoding) - it's buggy.

Use WebView#loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) instead.

 

loadData()はバグってるのでloadDataWithBaseURL()を使えとのこと。

どうバグってるのかはよくわかりません。

 

【Android】initLoaderとrestartLoader

AsyncLoaderを使っていると謎の挙動に出くわしたため調査

事象

 ①initLoader()→forceLoad()を実施

 ②onLoadFinished()が呼び出される

 ➂initLoader()→forceLoad()を実施

 ④onLoadFinished()が2回呼び出される←!!?!?!??

 

解決方法

initLoadeをrestartLoaderに変更することで解決

 

なぜなのか

Android Developersによれば

Ensures a loader is initialized and active. If the loader doesn't already exist, one is created and (if the activity/fragment is currently started) starts the loader. Otherwise the last created loader is re-used.

In either case, the given callback is associated with the loader, and will be called as the loader state changes. If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D) will be called immediately (inside of this function), so you must be prepared for this to happen.

下記の条件を満たしていると、onLoadFinished()が即座に呼び出されるもよう。

 ・コールバックの呼び出し側が開始状態(?)にある。

 ・ローダーがすでに存在していて、データが生成されている。

 

つまり、2回目のinitLoader()呼び出し時には、下記の流れになるようだ。

①initLoader()実行

②onLoadFinished()が即座に呼び出される。

➂forceLoad()によって再度Loaderが動き、onLoadFinished()が呼び出される。

 

 

 

【Android】AsyncTaskLoaderのテスト

色々探したが動かなかったりしたので、一応まとめる。

1,適当なアクティビティのテストを作成する。

f:id:noifuji:20151104013451p:plain

2,あらかじめ作成したAsyncLoaderに対して以下のコードを、テストケースに追加する。(赤字は書き換える)

 

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {

private static final String TAG = "MainActivityTest";
private MainActivity mActivity;
CountDownLatch mLatch;

public MainActivityTest() {
super(MainActivity.class);
}

public void setUp() throws Exception {
super.setUp();
setActivityInitialTouchMode(false);
mActivity = getActivity();
mLatch = new CountDownLatch(1);
}

@Test
public void testAsyncTaskLoader() throws Exception {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG, "run");
mActivity.getLoaderManager().initLoader(0, null,
new LoaderManager.LoaderCallbacks<AsyncResult<JSONArray>>() {
@Override
public Loader<Loaderのジェネリクス> onCreateLoader(int id, Bundle args) {
Log.d(TAG, "onCreateLoader");
作成したAsyncLoader名 loader = new 作成したAsyncLoader名(mActivity, 引数);
                         loader.forceLoad();
return loader;
}

@Override
public void onLoadFinished(Loader<Loaderのジェネリクス> loader,
Loaderのジェネリクス data) {
                       Log.d(TAG, "onLoadFinished");

//実行結果が正しいかここでチェックする。

mLatch.countDown();
}

@Override
public void onLoaderReset(Loader<Loaderのジェネリクス> loader) {
                     }
});
}
});
//UIスレッドが終了するまで待つ
boolean res = false;
Log.d(TAG, "await");
try {
res = mLatch.await(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d(TAG, "assert true");
assertTrue(res);
}

}

【DTI】はまったポイントと解決策-1-

cron.jsをデーモン化する

→pm2

github.com

 

[Android開発]ListViewの行ごとにレイアウトを変える

→Adapter内のgetView()に記述する。

 

[Android開発]非同期処理を複数作成したい

→AsyncLoader、Callbackを複数作成する。

https://groups.google.com/forum/#!topic/android-group-japan/-7ahRt6r_KI