とりあえず移転してみました

ニュースねたや、IT系の記事を書いていくつもり・・・ですが、どうなるかわかりません。まあ、とりあえず やってみます。

日本の文化という意味では・・・

海外で日本の文化とかに興味をもっている人とかを紹介したりする番組って多いのだけど、ちょっと愕然としてしまうことがある。
というのも、「漢字」「空手」「金魚」などのキーワードが出てくると、それって・・・・・・・

となってしまう。

漢字は、もう言うまでもなく「中国発祥」。日本で使われている漢字は、今中国で使われている漢字とは違うという意味では、日本オリジナルかも知れないけど、厳しい・・・

次に、空手・・・もう、これはついては元々「唐手」と言われていたように中国から沖縄に伝わったもの。
沖縄で「手(テイ)」と呼ばれる武術があったらしく、それと合わさったとも言われている。

空手の型には、「公相君(クーサンクー)」に関係する型が色々とある。公相君についても、色々と議論があるようだけど、中国から伝わったと言うのは疑いようがない。

さらに、沖縄から本土に伝わって「空手」という名前に変えて普及していくのだけど、本来日本にあった武道ではない。

古流の柔術が日本の古来の武道なので、古流柔術を元とする「柔道」は、日本の伝統のものとも言える。
自分が習っていた先生の先生は、流派を起こした沖縄の人で、名前から沖縄の人とわかる。当時は、沖縄から本土に来て空手を教える人が多かったらしい。

打撃系の武術が少なかったので、空手が一気に普及するきっかけになったのかも知れない。
それまでは、「剣道」が最強で素手の格闘技というのは、覚えるのが難しいうえに真剣相手ではちと厳しい。

さらに、日本の剣道は一番の弱点である刀が鞘に納まっている状態からも攻撃できるように「居合」というのまで出来てしまったので、古来の素手の武道では厳しい。

空手でも、同じなのだけど空手は武器術も含んだものなので、素手の技術の応用で武器(主に暗器)が使えるのが良かったのかも知れない。

日本の文化とかについて色々と考えさせられる事が多いけど、結局色々なものを吸収して独自に発展させる。これが日本文化なのかも知れない。

 

長篠の合戦 ライフリングの話の補足

nandarou.hateblo.jp

前回の記事の補足。
ライフリングの話で、銃身の内径より弾のほうが大きいからライフリングの意味があると書きましたが、銃身は硬い金属で作られます。ところが、弾は鉛です。

鉛をコーティングしたりしますが、基本は鉛です。
鉛と言えば、釣りの時に重りとして使ったりしますが、薄いものだと手で形を変えれるくらい柔らかいです。
弾が柔らかいので、鋼鉄の銃身の中を通っても、弾は止まったりしません。

爆発による燃焼ガスの押し出す力のほうが強いからです。
この時に、弾には旋条痕という独特の傷ができます。これで、銃を特定したりするのがアメリカのドラマCSIシリーズでも度々出てきます。

工業製品なので、基本的には同じように作るのですが、全く同じというわけではないですし、銃身以外の部分でも違いが出ますので、旋条痕も変わってきます。

工業製品でも個々のばらつきはあるので、ライフルでも優秀な製品だけを選抜して、カスタムするという方法で作られたH&K PSG-1というスナイパーライフルもあったりする。

ここまで書くと予測できるように、旋条痕を変えるには銃身を交換してしまえばいい。
銃身側のライフリングも、弾が発射されるたびに削られるので、発射数に応じて銃身をメンテナンスする必要がある。

 

地域ごとや年代で食べてる物が違うよね

昔の話をしている時に、「昔は、あれをよく食べたな・・・」なんて言っていると、周りから知らないと言われることがあったりする。
ところが、周りの人間の話を聞いても、知らない場合も多い。
地方出身者が多いと、それぞれの地域で全く知らないものの話になってしまう。

www.iitxs.com

久々に食べたくなるのが、この「マンハッタン」!!!

って、話をしても全然共感してもらえなかった。まあ、そりゃそうだ。福岡限定なの?
北部九州で食べれた記憶があったのだけどね?

このマンハッタンは、サクサクの生地にチョコがかけてある。サクサクなんだけど、中はしっとり。その食感の違いがGOOD
更に、チョコが全部かかっているわけではないので、チョコの味とノーマルの味が不定期で楽しめる。

子供の頃によく食べていたような・・・でも、どこにでも置いてあったように思ったので、特に貴重という意識はなかった。

似たようなものはあるのだけど、やっぱりマンハッタンは旨かった。

東京で売っているところないかな・・・

 

三段撃ちはあったのか?

有名な長篠の合戦。なぜ、有名なのかと言えば織田信長が鉄砲3千丁を使って、3段撃ちを行い最強騎馬軍団の撃破した戦いだったから。
これを検証している番組を見た。

まずは、火縄銃の撃つ間隔を計測していた。1発撃つのに30秒ほどかかっていた。
前装式の銃なので、銃を上向きにして火薬を入れて、弾を入れて棒を差し込んで奥まで装填。
そこから、構えて火蓋に火薬を入れ、火蓋を一旦閉じる。

火縄をセットしてから、狙いをつけて火蓋を空け、引き金を引く。

結構、大変。熟練の人でも30秒くらいはかかる。
3段撃ちは、装填に時間のかかる弱点を克服するために、撃った人が下がり後ろで装填。次に、用意できている人が撃つ。
また、後方に移動して装填という流れを順番に行う。

火縄銃というのは命中精度が50m以内であれば高く威力もあるので、50m以内に近づかないと効果が期待できない。

ところが、騎馬は50mの距離くらいでは8秒ほどで到達してしまう。

それを考慮して、3段撃ちを行っても騎馬のほうが早かった。

信長の3段撃ちというのは実際には、無理ではないか?というのが結論だった。
結局、それぞれの持ち場で準備できた人から撃つというのが早い。ということだった。

移動する時間がなくなるので、実際にはそっちが正解なのかも知れない。

この戦いについては、そもそも武田騎馬軍団というのが実際にはそれほど騎馬が多くなかったのでは?という話も出ている。
騎馬隊が有名だけど、全部騎馬なわけではないし、騎馬率は高いかも知れないけど、普通の編成だったのでは?と。

WWIIでは、ドイツの電撃作戦が有名になったけど、機械化歩兵と言われる車両をメインにしていた部隊は少なくて、後方の部隊では馬とか馬車で荷物を運んでいたらしい。

それは、現代でも同じようなもので自衛隊の戦車でも10式という最新戦車や90式という1つ前の戦車は少なくて、74式戦車がいまだに使われている。74式という名前が示すように1974年に制式化された戦車・・・

74式も少なくなってきたけど、まだ現役というのが凄い。同じようにF-4ファントムIIがまだまだ現役。
アメリカで開発された機体で、1960年に配備された機体。日本に配備されているのは改良がされているF-4EJ改で、生産されてから30年以上経過している。

F-4を改良した偵察機RF-4E、RF-4EJは、いまだにフィルム式なので偵察してから現像する必要があるとか・・・
このデジタルな時代で・・・
F-15偵察機に改修する案は、メーカーと揉めていた記憶が。

話は、戻って長篠合戦の番組の中で、火縄銃などの前装式と現代の後装式の違いを説明していた。
前装式は、ライフリングという溝がないので、安定しない。後装式は、ライフリングで弾が回転して安定すると。

ちょっと、説明していた絵がね・・・

前装式は、前から詰めていくので弾と銃身の間には隙間がないと弾が入っていかない。そのため、発射ガスが逃げてしまうので、威力も弱くなり、ライフリングを彫っても銃身と接していないので意味がない。

ところが、後装式は後ろから詰めるので弾が銃身の内側の幅より少し大きめ。その中を無理やり通っていくので、ライフリングの溝に沿って回転することになる。
説明の絵では、銃身と弾に隙間があった・・・残念・・・

 

android Fragmentまとめなど

FragmentとViewPagerで、はまったところのまとめ。
TabLatoutを使用して、タブ内でFragmentを表示する際に色々とはまってしまった。

流れとしては、以下のような感じ

・画面1(Activity)からアクセスするURLを決定

・webアクセスを実行して、結果を取得

・結果の中から次にアクセスするURLを2つ取得する

・webアクセスを2回実行して、結果を次の画面2(Activity)に表示する

・画面2には、TabLayoutを配置して、結果の2つをそれぞれのFragmentに表示

こんな流れだけど、問題だったのはwebアクセスは非同期処理ということ・・・
結果が返ってきてから、次の画面を表示としたのだけど、webアクセスをして画面2を表示してから、結果が返ってきたら反映・・・と想定していたけど、なかなか困難だった。

結果的には、結果が返ってきてから画面2の表示を行った。


まずは、Fragmentのおさらい

基本の部分は、以下のリンクで確認できる
フラグメント | Android Developers

newInstanseで初期設定を行い、onCreateViewで表示が行われる。
はじめから、Fragmentを生成する段階で、表示する値などを渡すほうがいいと思うのだけど、その方法だとFragmentがなんらかの要因で再表示される際に、データがないため例外処理で落ちてしまうらしい・・・

そこで、newInstanseで表示データなどをBundleで渡しておけば、再表示でもBundleからデータを持ってくるのでエラーにならない。

Fragmentのこの仕様のため、基本的に表示するデータを取得してから、Fragmentを生成しないと面倒。
TabLayoutを使う場合には、更にViewPagerAdapterを使ってFragmentを管理するので、ViewPagerAdapterから初期値を渡すことになる。

ViewPagerAdapterにBundleでデータを渡し、そのデータはViewPagerAdapterからFragmentにBundleでデータを渡す。
ListViewAdapterとかAdapterを使うことで、メリットは多いのだけど、データを渡すなどの処理を追加する場合は横断的に処理を行わないといけないので、面倒。

直接Fragmentにインターフェースを使って渡すことも可能なのだけど、Adapterが管理している以上はAdapterに処理を委譲しないと更新とかの処理が変になってしまう。

 

android 非同期処理まとめ

非同期処理は必要か?

androidで時間のかかる処理を行う場合には、マルチスレッドを利用してバックグランドで処理をする必要があります。新しいAPIでは、メインのスレッドでURLアクセスやDBアクセスを記述するだけでエラーになります。厳しい!!!

なので、必ず非同期処理が必要になってきます。
まずは、URLアクセス

okhttp3

便利なライブラリがあるので使います。okhttp3です。
build.gradle(app)にライブラリを使う宣言をします。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.squareup.okhttp3:okhttp:3.6.0' //<==追加

使用するclassでは、いつものようにimport文が必要。

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

これからが、本番です。

protected void urlAccess(String str){
        OkHttpClient client = new OkHttpClient();
        //RequestBody requestbodey = new FormBody.Builder()
        //        .build();

        Request request = new Request.Builder()
                .url(str)
                //.post(requestbodey)
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {
            final Handler mainHandler = new Handler(Looper.getMainLooper());
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                String callString = call.toString();
		//ここにViewの操作を記述する
                }
	}
}

メソッドを作成して、URLアクセスをする場合は、メソッドを呼び出すようにしています。URLは、引数として渡します。
POSTの場合の処理は、変わるのでコメントアウトしている部分がPOSTの場合の処理です。
サーバーからレスポンスがあった場合には、onResponseメソッドが実行されます。しかし、Handlerに登録するだけで実行されるのはHandlerの処理が空いた時になります。

この記述だけで非同期でのURLアクセスが可能になります。
ただ、このままでは足りません。非同期処理をメインスレッドで行わないのは、時間のかかる処理を別で行う間に画面上では別の処理を行いプログラムが止まったのか?重い処理をしているのか?を知らせる必要があります。

そのための非同期処理なので、追加でプログレスダイヤログを表示させます。

//フィールドに追加
private ProgressDialog progressDialog;

//メソッドとして追加
private void showProgressDialog(){
        progressDialog = new ProgressDialog(this);
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setMessage("WEBアクセス中です");
        progressDialog.setCancelable(true);
        progressDialog.show();
    }

showProgressDialog()を呼び出せば「WEBアクセス中です」と表示されたプログレスダイヤログが表示されます。
これで、プログラムがなにをやっているかわかります。

URLアクセスがあったら、次のコードで表示を消します。

progressDialog.dismiss();

Viewの操作になりますので、onResponseメソッド内に追加します。

@Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                String callString = call.toString();
		//ここにViewの操作を記述する
        progressDialog.dismiss();
                }

okhttp3ライブラリのおかげで、非同期処理も比較的楽に実装できます。

次に、AsyncTaskLoaderを使う方法です。ネット上でも色々とコードが出ていますので、参考に。

AsyncTaskLoader

まずは、AsyncTaskLoaderを継承した独自クラスを作成します。だいたい、こんなパターンで始まります。面倒なのですが。

public class AsyncDbLoader extends AsyncTaskLoader<List> implements LoaderManager.LoaderCallbacks{
    Bundle bundle;

    public AsyncDbLoader(Context context,Bundle args) {
        super(context);
        bundle = args;
    }

    @Override
    public List loadInBackground() {
        List listData;
        SQLiteDatabase myDatabase;
        Sql_db helper = new Sql_db(getContext());
        myDatabase = helper.getReadableDatabase();

        Cursor c = null;
        try {
            c = myDatabase.query("mainTable", null, null, null, null, null, null);

            listData = new ArrayList();

            //adapterにDBから文字列を追加
            boolean isEof = c.moveToFirst();
            while (isEof) {
                ArrayList<String> rowstring = new ArrayList<String>();
                rowstring.add(c.getString(1));
                rowstring.add(c.getString(2));

                listData.add(rowstring);
                isEof = c.moveToNext();
            }
        }
            finally {
            if (c != null) {
                c.close();
            }
            myDatabase.close();
            helper.close();
        }
        return listData;
    }

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

    @Override
    public Loader onCreateLoader(int id, Bundle args) {
        return null;
    }

    @Override
    public void onLoadFinished(Loader loader, Object data) {

    }

    @Override
    public void onLoaderReset(Loader loader) {

    }
}

実際にSQLiteからデータを取得しているコードですが、ここで重要なのはloadInBackgroundメソッドで結局、ここに実行する中身を記述するだけです。実行した結果を戻り値として返しています。

非同期でなければ、DBから取得した値をTextViewなどに書き込みわけですが、一旦List形式などにして返す必要があります。それを、メインスレッド側が受け取って、Viewに反映するという事になります。

呼び出す側のコードは、こんな感じで使います。showProgressDialogメソッドも入っていますので、プログレスダイヤログも表示されます。

getLoaderManager().initLoader(0,args, new AsyncDbLoader(this,args) {
            @Override
            public Loader<List> onCreateLoader(int id, Bundle args) {
                showProgressDialog();
                return new AsyncDbLoader(getContext(),args);
            }

            @Override
            public void onLoadFinished(Loader loader, Object data) {
                progressDialog.dismiss();
                List listData = (List)data;
                CustomAdapter adapter = new CustomAdapter(getContext(),2,listData,"list");
                ListView listView = (ListView)findViewById(R.id.listView);
                listView.setAdapter(adapter);
            }
        });

onCreateLoaderメソッドで、AsyncDbLoaderクラスのloadInBackgroundが実行されます。処理が終わるとonLoadFinishedが呼び出されます。ここでは、引数として渡されたdataをListとして格納して、ListViewに表示するまでの処理を行っています。
Viewへの変更ができるのはメイン側なので、ここでしか変更できません。

これで、非同期の処理としては2つの方法が可能で、URLアクセスの場合はokhttp3で簡単に記述でき、別の処理の場合は独自クラスを作成して、そのクラス内で処理を記述。
呼び出す側は、結果を受け取ってViewに反映という処理が必要です。

まあ、面倒といえば面倒なのですが、一度中身を理解してしまえば難しく感じません。

 

android ListViewでのはまりポイント

カスタムアダプターでListView

ListViewを使って、リスト形式の表示を行う場合が多いのだけど、色々とはまってしまった。
ListViewは、単純なテキストをリスト形式するのは簡単なのだけど、ちょっとカスタムしようとする場合は、カスタムしたクラスやレイアウトが必要になってくる。

ネットでも沢山情報があるので、基本的なところはできるのだが・・・

ArrayAdapterを継承したカスタムクラスを作成

CustomAdapter
public class CustomAdapter extends ArrayAdapter {
    private LayoutInflater layoutInflater_;

    public CustomAdapter(Context context, int textViewResourceId, List<String> objects) {
        super(context, textViewResourceId, objects);
        layoutInflater_ = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        if (convertView == null) {
                convertView = layoutInflater_.inflate(R.layout.rowdata_list, null);
        }

        ArrayList<String> item = (ArrayList<String>)getItem(position);

                TextView textView1;
                TextView textView2;
                textView1 = (TextView) convertView.findViewById(R.id.XXX);
                textView1.setText(item.get(1).toString());
                textView2 = (TextView) convertView.findViewById(R.id.XXX);
                textView2.setText(item.get(2).toString());

        return convertView;
    }
}

R.layout.rowdata_listというレイアウトファイルも作成

レイアウトファイル
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"
            android:id="@+id/textView1"
            android:layout_weight="3"
            android:textColor="@android:color/black"
            android:textSize="10sp" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceMedium"
            android:text="Medium Text"
            android:id="@+id/textView2"
            android:layout_weight="1"
            android:textColor="@android:color/black"
            android:textSize="10sp" />
    </LinearLayout>
</LinearLayout>

単純にTextViewが2つ並んでいるレイアウト・・・この部分を変更することで、レイアウトの変更も可能。

使う時は、CustomAdapterを使う。表示するListViewは(R.id.listView1)として指定している。

使う時のコード例
CustomAdapter adapter = new CustomAdapter(getContext(),0,listData);//listDataは表示させるデータ
                ListView listView = (ListView)findViewById(R.id.listView1);
                listView.setAdapter(adapter);

カスタムアダプターを使う場合は、色々と用意するものがあるけど、一度作れば使いまわせる。

はまったのは、カスタムアダプターを使わない場合。
カスタムアダプターは、ArrayAdapterを継承している。ArrayAdapterだけでも、単純なものでは使える。

ArrayAdapterでの使用例(失敗パターン)
ArrayAdapter adapter = new ArrayAdapter(getContext(),0,listData);
      ListView listView = (ListView)findViewById(R.id.listView1);
            listView.setAdapter(adapter);

CustomAdapterを使わずにArrayAdapterで指定してみた。
ここではまってしまった。テストをしてみるとアプリが落ちてしまう・・・しばらく原因がわからなかった。
ArrayAdapterを調べてみると、2つの引数が間違っていた・・・ここは、レイアウトファイルを指定しなければいけない。
カスタムアダプターと違うのだ。

R.layout.rowdataというファイルを新たに作成

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:background="@android:color/holo_blue_bright"
    android:padding="3dp">
</TextView>

TextViewが1つしかない単純なレイアウト・・・

ArrayAdapterでの使用例(成功パターン)
ArrayAdapter adapter = new ArrayAdapter(getContext(),R.layout.rowdata,listData);
      ListView listView = (ListView)findViewById(R.id.listView1);
            listView.setAdapter(adapter);

通常の場合でも、レイアウトファイルはいるのか・・・(面倒だ)

次に、カスタムアダプターに戻って、2行や3行のレイアウトはできるだろうか?リストによっては、1つの行の中で色々と表示したい場合がある。複数行にまたがる場合も当然あるだろうし、表示するものが多い場合もある。ウェブで見れるのはアイコンがあったり、2行くらいしなかない。

そこで、複数行のがいけるのか?やってみた。

結果としては、出来た。ファイルが長くなるので貼り付けはしないけど、LinerLayoutの下にLinerLayoutを4つ配置しても表示された。
そのレイアウトファイルをカスタムアダプターの中で読み出してあげればいい。
R.layout.rowdata_listの部分を変更する。もしくは、R.layout.rowdata_list自体を変更してもいい。