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

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

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

 

下記を参照した

try catch and ...release: [Node.js] 複数のHTTPリクエストを同期的に行うサンプル

 

var urls = ["abc.com", "xyz.com"];

function execRequest(idx) {
    url = urls[idx];
    console.log("executing execRequest()... url:", url);

    // exec http request
    http.get(url, function(response) {
    if (response.statusCode == 200) {
        //ここに成功した時の処理を書く
    }

    // 次のリクエストを呼ぶ。
    // 全てのリクエストを実行し終えたら、コールバックを投げる。
    if (idx + 1 < length) {
        console.log(" execute execRequest() after 1000ms...");

        // execute the recursive function "execRequest()" after 1000 ms
        setTimeout(function() {
            execRequest(idx + 1);
        }, 1000);
    } else {
        return callback();
    }});
}

// fire the recursive function "execRequest()"
execRequest(0);

 

 

【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);
}

}

【Android】AsyncLoaderでのエラー処理

AsyncLoaderでのエラー処理

下記の記事を参照

just my two cents: Android: AsyncTaskLoader Exception Handling

【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