パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください -24ページ目

パークのソフトウエア開発者ブログ|ICT技術(Java・Android・iPhone・C・Ruby)なら株式会社パークにお任せください

開発の解決方法や新しい手法の情報を、パークのエンジニアが提供します。パークのエンジニアが必要な場合は、ぜひお気軽にお問い合わせ下さい。 株式会社パーク:http://www.pa-rk.co.jp/

会員No.18です。

『paiza.IO』とはブラウザ上でコードを書け、書いたコードをその場で実行できるオンラインのプログラム実行環境です。環境を作るのが面倒、すぐに試してみたいというときに便利です。下記24言語に対応しています。勉強会等で使えそうです。

C、C++、C#、Java、Ruby、Python2系、Python3系、PHP、Perl、JavaScript、Objective-C、Scala、Go、Haskell、CoffeeScript、Bash、Erlang、R、COBOL、VB、F#、MySQL、Clojure、D


Twitterからもコードを実行でき「@paiza_run」または「#paiza_run」で始まるメッセージを送ることにより実行結果をリプライで受け取ることができるそうです。リプライを受けるには@paiza_runをフォローする必要があります。


URL:https://paiza.io/
こんにちわ。ゆんぼうです。

今回は、Androidアプリでタブを作成します。
開発環境は以下の通りです。
・Eclipse v4.2.1
・Android 4.4.2

はじめに、Androidアプリのタブについて記載します。
Android v3.x (Androidコードネーム:Honeycomb)以前は、TabActivity や TabHostのクラスを使用していました。
・android.app.TabActivity
・android.widget.TabHost


しかし、3.x 以降では、非推奨APIとなっています。
代わりに、Fragment や ActionBar を使用してタブを作成します。
・android.app.ActionBar
・android.app.Fragment



■シンプルなタブを作成

タブの名前を表示しただけのシンプルなタブを表示した画面を作成します。
MainActivity.java にタブを表示する処理を実装します。

package jp.co.pa_rk.test_tab.activity;

import jp.co.pa_rk.test_tab.R;
import jp.co.pa_rk.test_tab.fragment.Tab1Fragment;
import jp.co.pa_rk.test_tab.fragment.Tab2Fragment;
import jp.co.pa_rk.test_tab.fragment.Tab3Fragment;
import jp.co.pa_rk.test_tab.fragment.Tab4Fragment;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity { // (1)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // (2)

        // タブにリスナーを追加する
        createTab(actionBar, new MainTabListener<Tab1Fragment>(this, Tab1Fragment.class), "タブ1");
        createTab(actionBar, new MainTabListener<Tab2Fragment>(this, Tab2Fragment.class), "タブ2");
        createTab(actionBar, new MainTabListener<Tab3Fragment>(this, Tab3Fragment.class), "タブ3");
        createTab(actionBar, new MainTabListener<Tab4Fragment>(this, Tab4Fragment.class), "タブ4");

        // デフォルトの状態選択を変更する
        actionBar.setSelectedNavigationItem(0);
    }

    /** タブリスナークラス */
    public static class MainTabListener<T extends Fragment> implements ActionBar.TabListener {

        private Fragment _fragment;
        private final Activity _activity;
        private final Class<T> _cls;

        public MainTabListener(Activity activity, Class<T> cls) {
            this._activity = activity;
            this._cls = cls;
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            _fragment = Fragment.instantiate(_activity, _cls.getName());
            ft.replace(android.R.id.content, _fragment); // (4)
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
        }
    }

    /**
     * タブを作成する
     */
    private void createTab(ActionBar actionBar, MainTabListener<?> listener, String title) {
        ActionBar.Tab tab = actionBar.newTab();
        tab.setTabListener(listener);
        tab.setText(title);
        actionBar.addTab(tab); // (3)
    }
}


(1)タブには Fragment を使用するため、FragmentActivity を継承します。
(2)アクションバーでタブ表示を行うモードに設定します。
(3)各タブのFragmentのインスタンスとタブに表示する文字列を設定して、アクションバーに追加します。
(4)タブ切り替え時に、切り替え先のFragmentに置き換えます。

MainActivity の View は下記の通りです。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tab_contents"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>


Tab1Fragment にタブの内容を実装します。

package jp.co.pa_rk.test_tab.fragment;

import jp.co.pa_rk.test_tab.R;
import jp.co.pa_rk.test_tab.R.id;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * tab 1
 */
public class Tab1Fragment extends Fragment { // (5)

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_tab1, container, false);
        TextView textView = (TextView) view.findViewById(id.text);
        textView.setText("メッセージ1"); // (6)
        return view;
    }
}


(5)Fragment を継承します。
(6)タブの切り替えが分かりやすいように、テキストを表示します。
※Tab1Fragment と同様に、クラス名及び、テキストの内容を変更して、
Tab2Fragment, Tab3Fragment, Tab4Fragment を作成します。

Tab1Fragment, Tab2Fragment, Tab3Fragment, Tab4Fragment に対する View は下記の通りです。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

ファイル構成は、以下の通りです。

root
├─res
│  └─layout
│          activity_main.xml
│          fragment_tab1.xml
│          fragment_tab2.xml
│          fragment_tab3.xml
│          fragment_tab4.xml
└─src
    └─jp
        └─co
            └─pa_rk
                └─test_tab
                    ├─activity
                    │      MainActivity.java
                    │     
                    └─fragment
                            Tab1Fragment.java
                            Tab2Fragment.java
                            Tab3Fragment.java
                            Tab4Fragment.java

アプリを実行したときのスクリーンショットは下記の通りです。
 

■アイコン付きタブを作成

次に、アイコン付きのタブを作成します。
今回は、Android公式サイトで配布されているアイコンの画像ファイルを使用します。
Action Bar Icon Pack
https://developer.android.com/design/downloads/index.html

取得したアイコンの画像ファイルを下記の構成になるように配置します。

root
└─res
    └─drawable-hdpi
            icon_tab1.png
            icon_tab2.png
            icon_tab3.png
            icon_tab4.png

MainActivity の createTab()メソッドの処理を変更します。

private void createTab(ActionBar actionBar, MainTabListener<?> listener, int iconId, String title) {
   ActionBar.Tab tab = actionBar.newTab();
   tab.setText(title);
   tab.setIcon(iconId); // (7)
   tab.setTabListener(listener);
   actionBar.addTab(tab);
}

(7)アイコンをタブに設定して、アクションバーに追加します。
呼び出し側は下記の通りになります。

createTab(actionBar, new MainTabListener<Tab1Fragment>(this, Tab1Fragment.class), R.drawable.icon_tab1, "タブ1");
createTab(actionBar, new MainTabListener<Tab2Fragment>(this, Tab2Fragment.class), R.drawable.icon_tab2, "タブ2");
createTab(actionBar, new MainTabListener<Tab3Fragment>(this, Tab3Fragment.class), R.drawable.icon_tab3, "タブ3");
createTab(actionBar, new MainTabListener<Tab4Fragment>(this, Tab4Fragment.class), R.drawable.icon_tab4, "タブ4");


アプリを実行したときのスクリーンショットは下記の通りです。


■タブのViewをカスタマイズする

次に、タブのViewをカスタマイズします。

カスタマイズ用のViewは、下記の通りです。
※tab2.xml, tab3.xml, tab4.xml もViewIdのみが異なり、その他は同様の内容になっています。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <ImageView
        android:id="@+id/tab1_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent" />
    <TextView
        android:id="@+id/tab1_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>


カスタマイズ用のViewは、下記の構成になるように格納します。

root
└─res
    └─layout
            tab1.xml
            tab2.xml
            tab3.xml
            tab4.xml

MainActivity の createTab()メソッドの処理を変更します。

private void createTab(ActionBar actionBar, MainTabListener<?> listener, int tabId, int tabIconId, int tabTitleId, int iconId, String title) {
    ActionBar.Tab tab = actionBar.newTab();
    tab.setCustomView(tabId); // (8)
    tab.setTabListener(listener);
    actionBar.addTab(tab);
    TextView textView = (TextView) findViewById(tabTitleId); // (9)
    textView.setText(title);
    ImageView image = (ImageView) findViewById(tabIconId); // (10)
    image.setImageResource(iconId);
}


(8)カスタマイズ用のViewを設定します。
(9)カスタマイズ用のViewのViewIdからタブのタイトルを設定します。
(10)同様にViewIdからタブのアイコンを設定します。

呼び出し側は下記の通りになります。

createTab(actionBar, new MainTabListener<Tab1Fragment>(this, Tab1Fragment.class), R.layout.tab1, R.id.tab1_icon, R.id.tab1_title, R.drawable.icon_tab1, "タブ1");
createTab(actionBar, new MainTabListener<Tab2Fragment>(this, Tab2Fragment.class), R.layout.tab2, R.id.tab2_icon, R.id.tab2_title, R.drawable.icon_tab2, "タブ2");
createTab(actionBar, new MainTabListener<Tab3Fragment>(this, Tab3Fragment.class), R.layout.tab3, R.id.tab3_icon, R.id.tab3_title, R.drawable.icon_tab3, "タブ3");
createTab(actionBar, new MainTabListener<Tab4Fragment>(this, Tab4Fragment.class), R.layout.tab4, R.id.tab4_icon, R.id.tab4_title, R.drawable.icon_tab4, "タブ4");


アプリを実行したときのスクリーンショットは下記の通りです。

以上です。

AWS LABを利用することにより無料で色々と試せます。(ただし30分)
30分後には、きれいさっぱり消えちゃいます。

やってみたこと
◆東京リージョンにEC2インスタンスを1台起動
 インスタンス起動前のキーペアの作成
 AWSが提供しているAmazon Linux AMIを利用
 Public DNS名を使ってインスタンスにログイン
 インスタンスにhttpdのインストール
 ブラウザからのアクセス

■前準備
 AWS LABを使用するにあたり、以下サイトでアカウント作成が必要になります。
 https://run.qwiklabs.com/

 teratermのインストール

 実際にやってみた、手順(キャプチャ)は以下にあります。
AWS_LAB_1.pdf」を参照ください。
Windows Server 2012 R2 を 推奨の状態でインストールしたあと、とても使いにくかったので、GUIを追加しました。

備忘録的に書いておこうと思います。

・Windows Server 2012 R2 のインストールを実施
・インストール時の容量も少なく済むので、ServerCore(推奨)でインストール

ServerCoreでインストールを実施すると、起動時コマンドプロンプトのみが表示され、
すべての操作はそこから行わなくてはなりません。

★分かってはいましたが、かなりの不便さを感じました。

そこで、サーバーマネージャだけでもGUIをインストールしよう!と以下のコマンドを実施
(使用した環境ではDVDドライブが”F”でした)

Install-WindowsFeature Server-Gui-Mgmt-Infra,Server-Gui-Shell -Source:wim:F:\sources\install.wim:4 -restart

インストールの開始が表示され、インストールが開始されました。
(68%までは順調に進みましたが、その先が進まず不安になりました。)

再起動後、コマンドプロンプトがまず表示され、その後サーバーマネージャが表示されるようになりかなりの満足です。

しばらくそれで満足していましたが、重ねて他のGUIも表示、使用可能なようにインストール。
Install-WindowsFeature Server-Gui-Mgmt-Infra,Server-Gui-Shell -Source:wim:F:\sources\install.wim:2 -restart

飽きたら、GUIをアンインストールし、ServerCoreだけに戻そうと思います。

気持ちよさ

おひさしぶりです、ちかです
いつもながら記事全体が個人の感想です。

気持ちよくコーディングするためには
不安や恐怖をなくす必要があります。

  • 呼んでる関数に余計な副作用があるんじゃなかろうか。
  • 例外が飛んでくるんじゃなかろうか。
  • 境界値で落ちるんじゃなかろうか。
  • リソースの解放がダダモレなんじゃなかろうか。
  • マルチスレッドはスリル、ショック、サスペンスなんじゃなかろうか。
  • このソフトウェアは世界中の誰の役にも立たないんじゃなかろうか。

不安や恐怖がなくて、問題の解法に集中できて、秒単位で編集 - 実行ループできるなら、
コーディングは気持ちいいものになるのではないかと思います。

D 言語の場合

ということを踏まえて
D 言語で 2 つの非負整数の最大公約数を求めてみます。
 # コンパイラーは Windows 版 DMD 2.0.65 を使っています。

  • ユークリッドの互除法 - Wikipedia
    1. 入力を m, n (m ≧ n) とする。
    2. n = 0 なら、 m を出力してアルゴリズムを終了する。
    3. m を n で割った余りを新たに n とし、更に 元の n を新たに m とし 2. に戻る。

gcd.d

import std.typecons;
 
unittest {
    assert(gcd(0, 0) == 0);
    assert(gcd(0, 1) == 1); // すべての整数は 0 の約数
    assert(gcd(uint.max, 0) == uint.max);
    assert(gcd(1, 1) == 1);
    assert(gcd(21, 10) == 1);
    assert(gcd(18, 24) == 6);
    assert(gcd(2 * 2 * 3 * 5 * 7, 2 * 2 * 7 * 11) == 2 * 2 * 7);
    assert(30.gcd(75) == 15);
}
/// 2 つの非負整数の最大公約数を算出します。
pure nothrow auto gcd(uint x, uint y) {
    auto pair = x < y ? tuple(x, y) : tuple(y, x);
    while (pair[0] != 0) {
        pair = tuple(pair[1] % pair[0], pair[0]);
    }
    return pair[1];
}

アルゴリズムをそのまま書き下したかのようにシンプルですが
ここには安心と気持ちよさが詰まっています。

世界中の誰の役にも立たないでしょうけどね…(苦笑)

D 言語の機能紹介

■ unittest ブロック

動作に不安があるなら試しましょう!

unittest で始まるコードブロックは、
コンパイルオプション -unittest をつけたときだけコンパイルされ、
実行時にエントリポイント (main 関数) の前に実行されます。

ファイルごとに単体でテストを走らせることもできますし、
「開発版では起動するたびに単体テストが走る」ようにもできます。

関数やクラス定義の近くに unittest ブロックを置くことで、使用法の例示にもなります。

テストをパスすると気持ちいい!

■ pure

純粋関数 (副作用がなく、一貫性がある関数) ですよ、という宣言 (関数の修飾子) です。

コンパイラーがチェックしてくれます;
関数の外のスコープにある変更可能な変数へアクセスしたり、 pure でない関数を呼んだりすると、コンパイルエラーになります。
I/O API などはもちろん非 pure なので呼び出せません。

ただなぜか引数値を変更してもコンパイルエラーにならないため、
きちんと純粋性を表現するには、関数に対する pure 修飾だけでなく、参照型引数に対する const 修飾が必要です。
Effective C++ 『可能ならいつでも const を使おう』は D 言語でも健在です。

純粋関数は「『状態』をもたず、つくらず、もちこませず」の原則を現実のものにします。

  • 副作用がないので、バグがあったとしても戻り値がおかしくなるか例外が飛ぶだけです。『状態』をおかしくすることはありません。
  • 一貫性があるので、「これこれこういうときだけ再現する」といった状態依存バグが起きません。
  • 複数のスレッドから同時に実行できます。排他制御は要りません。
  • 単体テストは引数と戻り値の関係だけ検証すれば済みます。
    (副作用のある関数の場合、事後状態を検証する必要があります。一貫性のない関数の場合、事前状態による振る舞いの違いを検証する必要があります。これらは本当に骨が折れます。。)

pure だらけのコードは気持ちいい!
 # D 言語でなくても関数の純粋性には配慮すべきですね!

■ nothrow

例外 (Exception) を投げませんよ、という宣言です。

ただ残念ながら、 nothrow によって得られる安心は限定的です;
Java の throws と同様、 Exception 以外にも投げられうる Throwable があり、
コンパイラーがチェックしてくれるのは Exception だけです。

■ import

最初の行ではタプルを使うために std.typecons をインポートしています。

一般にインポートには 2 種類あります。

  1. 機能を取り込むために必要なインポート (C/include, Python/import, Ruby/require など)
  2. 名前空間を省略するためだけのインポート (Java/import, C#/using など)

D 言語のインポートは 1. にあたり、機能を取り込むために必要です。

ところで...
上のサンプルコードでは、名前空間修飾せずにシンボル tuple を使っています。
「グローバル名前空間が汚されるのか…」と私も最初は恐怖しました。

が、
実際にはシンボルは名前空間 std.typecons 配下にインポートされており、
名前が競合していないシンボルに限り 名前空間を省略してアクセスできます。

■ UFCS (Uniform Function Call Syntax)

D 言語では、 30.gcd(75)gcd(30, 75) と同じ結果になります。
すなわち、関数は第 1 引数の型の値に対してメソッドの構文で呼び出すことができます。
C# の拡張メソッドがすべての関数に適用されるイメージですね。

C#/LINQ によるシーケンス操作や jQuery による DOM 操作をしたことがあれば分かると思うのですが、
メソッドチェインって気持ちいいんです!

import std.algorithm;
import std.array;
import std.stdio;
 
void main() {
    [-3, 7, -2, 6, -8, 4, 6]
        .filter!(x => x > 0)
        .map!(x => x * x)
        .array.sort.uniq.writeln;
    // 標準出力に [16, 36, 49] と出力されます。
 
    // filter, map, array, sort, uniq, writeln はいずれもメンバーでない関数です。
    // 関数呼び出しのカッコは引数がなければ省略できるので省略しています。
    // ! (テンプレート引数) やラムダ式 (x => x > 0) は未紹介ですが、全体の雰囲気を感じていただければ。
}

ぜんぜん紹介できてませんけど

例が簡単すぎて出てきてませんが(汗)、
D 言語はオブジェクト指向プログラミングの機能をサポートしています。
C++, Java, C# のいいとこどりな感じなのですが、長くなりそうなのでまた別の機会に。

それはそれとして、もう少しだけ、不安や恐怖を拭い去る機能を紹介しましょう。

■ const と immutable
  • const 修飾された型の変数は不変です。
    C++ の const より「深い」不変性を保証します; クラスや構造体であれば、メンバーも、メンバーのメンバーも、 … 、変更できません。
    ただし、同じインスタンスを参照する別の変数から変更される可能性はあります。
  • immutable 修飾された型の変数は不変です。
    const とは異なり、 immutable な型の変数に immutable でない型のインスタンスを代入することはできません。
    初期化したら 2 度と変更できません。
void main() {
    auto mutable = new Object;
    const constant = mutable;                         // OK
    immutable fakelyImmutable1 = mutable;             // コンパイルエラー
    immutable fakelyImmutable2 = constant;            // コンパイルエラー
    immutable reallyImmutable = new immutable Object; // OK
    const actuallyImmutable = realImmutable;          // OK
}
■ リソースリーク対策
  • ガベージコレクションがあります。無効にもできます。
  • C++ の RAII イディオム が使えます。さらに、D 言語独自の scope を使うとブロックを抜けるときの処理を予約できます。 try-finally も使えますが必要になることはないと思います。
■ マルチスレッディング
  • グローバル変数や静的変数は明示的に共有しない限りスレッドローカルになります。
  • 共有変数の排他制御には Java と同じ synchronized ブロックを使えます。
■ 契約プログラミング
  • 私はまだこのパラダイムに触れていないのでよく分かりません。。

D 言語は、スクリプト言語の表現力、コンパイル言語の堅牢性、ネイティブのパフォーマンスを持つ「なんでもあり言語」です。
1 度触れてみてはいかがでしょうか。

リンク