ラベル Java の投稿を表示しています。 すべての投稿を表示
ラベル Java の投稿を表示しています。 すべての投稿を表示
2014/12/30

2014年に @wada811 が読んだ技術書まとめ

2014年も終わりに近づいているので@wada811が読んだ技術書を振り返ってみようかと思います。
2013年はこちら→2013年に @wada811 が読んだ技術書まとめ | DevAchieve(11冊)
2012年はこちら→2012年に @wada811 が読んだ技術書まとめ | DevAchieve(約40冊)

2014/05/07 [書評]ノンデザイナーズ・デザインブック | DevAchieve

色々な所で読んでおくべきデザイン本として紹介されている本です。
4つの基本原則も良いけど、個人的にはジョシュア・ツリーの悟りの話が好きです。
一度名前を呼ぶことができれば、
あなたはそれを意識し、それを支配し、それを所有し、
それをコントロールできるようになる。
名前大事ですね。

1年で書籍1冊の書評を書いた!

全然読んでないけど大丈夫か、という感じだ…。
Linuxエンジニア養成読本は職場にあったので読んだけど
【改訂新版】Linuxエンジニア養成読本が出ていた。
他の事に時間使っていて本読んでない…。

2014年に @wada811 が積んだ技術書まとめ

増補改訂版Java言語で学ぶデザインパターン入門
増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編
JUnit実践入門 体系的に学ぶユニットテストの技法
レガシーコード改善ガイド
Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築

重い本ばっかり積んでる…。
手を動かしつつ、ちゃんと本も読んでいきたい。
2014/01/12

[書評]Effective Java 第2版

Effective Java 第2版 (The Java Series)
著者 : Joshua Bloch
ピアソンエデュケーション
発売日 : 2008-11-27
ブクログでレビューを見る»
Java中級者以上なら読むことがマナーであると言われるJavaの必読書。
内容が難しいのか訳がわかりにくいのか理解度が低いのかわからないけども、
内容が理解できない部分もあったが必ず役に立つと感じさせられた。
期間をあけて何度か読んで理解度を上げて実践していきたい。
Java は Android アプリ開発のために独学でろくに入門書も読まずに勉強したので
ベストプラクティスとか正しいやり方・マナー的な部分を全然知らずに開発していました。
基本的に Android アプリは一人で開発していてコードレビュー的なこととか全くしたことがなかったので
果たしてちゃんと Java を書けているのだろうかという疑問がありました。
そんな時に Effective Java は Java を書くなら読んでおくべきだよねーという意見を聞いたので
読まなくてはと思いました。(思っただけで実際に読むまでは時間が空きましたが。)

結局、読まなくてもなんとなく書けるので中々読もう!というところまで行かないんですね。
転機が訪れたのは Effective Java の出版元であるピアソンエデュケーション(ピアソン桐原)が
ピアソングループを離脱したことによって技術系の書籍が入手困難になったことでした。
ピアソンの技術書は書店在庫限りとの見通し。ピアソン桐原社がピアソングループ離脱で(追記あり) - Publickey
そういうわけで入手できなくなる前に Amazon で入手して読むに至りました。

良かったことに、丸善出版さんが Effective Java 第2版だけでなく他の書籍も再出版してくれるそうです。
[丸善出版] 旧・ピアソン桐原より翻訳刊行されていた書籍を、一部再出版することになりました。
ピアソンエデュケーション:Effective Java 第2版
丸善出版:EFFECTIVE JAVA 第2版
もうすでに Amazon で予約することができます。

ところで内容ですが、enum と並列性の部分はあまり馴染みのない部分だったので役に立ちました。
アノテーションと Serializable は使ったことがないのでまだ良くわかりませんでした。
他の部分はなんとなく知っていただけどちゃんとした知識として入ってはいなかったので良かったです。
ちゃんと理解できるとソースコードの見え方が違って見えるので読んでよかったなと思います。
それこそ TimeUnit クラスの実装を見て、あ!これ Effective Java でやったやつだ!ってなりました。
Java を書くならオススメだと思います。
2013/12/30

2013年に @wada811 が読んだ技術書まとめ

2013年も終わりに近づいているので@wada811が読んだ技術書を振り返ってみようかと思います。
2012年はこちら→2012年に @wada811 が読んだ技術書まとめ | DevAchieve(約40冊)

2013/03/02 [書評]正規表現辞典 | DevAchieve

正規表現辞典は本当に良い。
通読しても良し、かいつまんで読んでも良し、辞書としても良しの三拍子揃った素晴らしい書籍です。
正規表現が使えれば大抵のテキスト処理は簡単にできるのでエンジニアもそうでない人も読んだほうが良いです。
ついでに僕の Amazon リンクから買うとアフィリエイト料が入ってなお良しです。
(最近、アフィリエイト料率が下がって全然儲からないです。つらい。)

2013/05/31 [書評]モバイルデザインパターン | DevAchieve

デザイン系の書籍は [書評]iPhoneアプリ設計の極意 ―思わずタップしたくなるアプリのデザイン に続いて2冊目。
会社にあったので読んでみた。内容的にはiPhoneアプリ設計の極意とそんなに変わらないかも。
それぞれのデザインパターンについて簡潔な説明でまとめた付録がわかりやすかった。どちらか一冊で良さそう。
もう一冊読むなら一味変えてインタフェースデザインの心理学を読んだほうが得るものありそう。
あと、ユーザビリティで有名っぽいニールセン博士のモバイル・ユーザビリティも微妙に気になってる。
へいしゃー!買ってくれー!間に合わなくなっても知らんぞー!!

2013/08/25 [書評]HTTPの教科書 | DevAchieve

概要を知るには良い感じの本です。挿絵とか文体とか読みやすくてわかりやすかったです。
Web 関連の技術や必要な知識についてHTTPの教科書のテイストで解説している本があったら
Web 系プログラマの新人教育に使えそうな気がします。
Web への攻撃技術という章でセキュリティ関連の解説もわかりやすく行われているので大変良いです。
(引越に際して売ろうかと思っていたけど取っておこうかな)

2013/08/29 [書評]達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ | DevAchieve

データベース初心者がSQLを極めるためのオススメ書籍6冊の本のうち、読んだ本3冊目です。
ちなみに達人に学ぶ SQL徹底指南書は読んでません。
結構 SQL は書けるようになって複雑なのとか行けるようになったから
そこまで切羽詰まってないので達人に学ぶ SQL徹底指南書はいいかなぁって感じです。
それより DB 設計とかパフォーマンスチューニング的な所を身につけていきたいです。
DB 設計については達人に学ぶDB設計 徹底指南書が良かったので何とかなりましたが、
パフォーマンスチューニングはどこから知識を得ればいいんでしょうね?
数十万件規模のテーブルをジョインジョイントキィするとサービスをKOしてしまって
開発第二ラウンドが発生してしまうので勘弁願いたいんですよねぇ。

1年で書籍4冊の書評を書いた!

2012年は約40冊読んで25冊くらい書評書いたのに今年少なすぎじゃないか?アカン…。
まぁその分DevCameraの開発にかなりの時間を割いたし、
書籍を読む以上に Androider としての技術力が上がったから良いかな?
Android の NDK とか OpenGL, OpenCV のような特殊な事以外だったら
書籍無くてもリファレンスとか見てだいたい実装できそうな気がする。
まぁアニメーションとか UX 的な気持ちよさみたいな部分の実装能力はまだまだだけど。

読んだけど書評を書いていないのは以下の7冊かな。
【改訂新版】 Linuxコマンド ポケットリファレンス
良かった。手元においておきたい感じだけど
普段使うコマンドってそんなに変わらないから使用機会が少ないのが難点。
しかも家に置いてあるという。会社だったらググって解決なので使い所が難しい。
入門UNIXシェルプログラミング
まだ読み途中で積ん読になってる…。
興味はあるし、ちょっとしたシェルスクリプトで手間が省けたら嬉しいから学びたいけど
いかんせん使用機会の少なさがモチベーションの低さになってしまう。
入門 Androidアプリケーションテスト
UnitTest やろうというのが2013年の目標だったので買ってみた。
しかし、開発したアプリがカメラ機能がメインなのでテストがやりにくくて全然やってない。
仕事でカメラとか端末機能を使わないアプリでは UnitTest をやれたので良かったと思う。
Smashing Android UI レスポンシブUIとデザインパターン
デザイン系の書籍3冊目で、珍しく Android をテーマにしたデザインパターン本です。
凄く良い本だったし、ちゃんと書きます。放置しててごめんなさい…!
書きました→[書評]Smashing Android UI レスポンシブUIとデザインパターン | DevAchieve
OpenGL ES 2.0 Androidグラフィックスプログラミング
OpenGL ES を Android から呼び出す方法を解説している本です。コレも記事書きます…!
年をまたいでしまう…!ごめんなさい…!
書きました→[書評]OpenGL ES 2.0 Androidグラフィックスプログラミング | DevAchieve
Effective Java 第2版
ピアソン桐原社の技術書などが在庫限りという事で入手困難に陥る前に買いました。
記事書きます…!読んだらすぐに書評書かないとダメだ…!
書きました→[書評]Effective Java 第2版 | DevAchieve
プレゼンテーションZen 第2版
こちらもピアソン桐原社の書籍で、会社にあったので読みました。
4月になる前にこのへんの書籍の書評を書こう…!

Android も良いけど他のことももっと色々出来るようになっていこう!
そしてちゃんと書評記事を書こう!速さが足りない!
2013/11/29

ExecutorServiceでマルチスレッドで実行可能なタスクキューを使う

マルチスレッドシリーズその2。
その1はこちら→[Java]マルチスレッドでの排他処理を行うsynchronizedを理解する
前回と同じく理解するためにサンプルを Android で作ってみました。

参考
ExecutorService の使い方 - Java 入門(図や概念がわかりやすい!)
Java - ExecutorService の復習 - Qiita [キータ](動作の違いがわかりやすい!)
死刑執行中 ExecutorService 終了中 - 倭マン's BLOG
[Java]ExecutorServiceの正しい終了(shutdown)の仕方 | 大発見 | 大発見

サンプルコードは以下にあります。
ExecutorActivity.java | wada811/AndroidLibrary@wada811
AndroidLibrary ってなってるけどやっぱりコレは Android 関係ないです。

実行するタスク

名前と実行時間(sleep時間)を貰ってログを出力するだけのクラス。以後、共通で使います。
public class ExecutorRunnable implements Runnable {
    private String mName;
    private int mSeconds;

    public ExecutorRunnable(String name, int seconds) {
        mName = name;
        mSeconds = seconds;
    }

    @Override
    public void run(){
        LogUtils.d(mName + ": ThreadId: " + Thread.currentThread().getId());
        LogUtils.d(mName + ": start");
        try{
            TimeUnit.SECONDS.sleep(mSeconds);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        LogUtils.d(mName + ": end");
    }
}

Executors.newSingleThreadExecutor();

public void newSingleThreadExecutorTest(){
    LogUtils.d();
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(new ExecutorRunnable("A", 1));
    executorService.submit(new ExecutorRunnable("B", 1));
    executorService.submit(new ExecutorRunnable("C", 1));
    executorService.submit(new ExecutorRunnable("D", 1));
}
SingleThread なのでタスクをいくつ追加しても一つのスレッドで実行します。追加した順に実行されます。
実行中だったら待たされます。実行ログからもそのことがわかります。
11-27 23:50:49.697: [ExecutorActivity#newSingleThreadExecutorTest:108]
11-27 23:50:49.707: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27824
11-27 23:50:49.707: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-27 23:50:50.708: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-27 23:50:50.708: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27824
11-27 23:50:50.718: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-27 23:50:51.719: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-27 23:50:51.719: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27824
11-27 23:50:51.719: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-27 23:50:52.720: [ExecutorActivity$ExecutorRunnable#run:306]C: end
11-27 23:50:52.720: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27824
11-27 23:50:52.730: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-27 23:50:53.731: [ExecutorActivity$ExecutorRunnable#run:306]D: end

Executors.newFixedThreadPool(int);

public void newFixedThreadPoolTest(){
    LogUtils.d();
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    executorService.submit(new ExecutorRunnable("A", 1));
    executorService.submit(new ExecutorRunnable("B", 1));
    executorService.submit(new ExecutorRunnable("C", 1));
    executorService.submit(new ExecutorRunnable("D", 1));
}
引数のスレッド数で実行します。今回は2スレッドで実行します。追加した順に実行されます。
実行ログからも A, B と実行され、 A が終わったら C、B が終わったら D と実行されていることがわかります。
11-27 23:56:04.974: [ExecutorActivity#newFixedThreadPoolTest:124]
11-27 23:56:04.984: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27825
11-27 23:56:04.994: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-27 23:56:05.024: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27826
11-27 23:56:05.034: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-27 23:56:05.995: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-27 23:56:05.995: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27825
11-27 23:56:05.995: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-27 23:56:06.035: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-27 23:56:06.035: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27826
11-27 23:56:06.045: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-27 23:56:07.006: [ExecutorActivity$ExecutorRunnable#run:306]C: end
11-27 23:56:07.046: [ExecutorActivity$ExecutorRunnable#run:306]D: end

Executors.newCachedThreadPool();

public void newCachedThreadPoolTest(){
    LogUtils.d();
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.submit(new ExecutorRunnable("A", 1));
    executorService.submit(new ExecutorRunnable("B", 1));
    executorService.submit(new ExecutorRunnable("C", 1));
    executorService.submit(new ExecutorRunnable("D", 1));
}
必要な分だけ(※)スレッドを生成して実行します。
(※ 内部の処理を見ると Integer.MAX_VALUE とあるので限界は int の最大値?)
タスクが何個 submit されようと必要に応じてスレッドを生成して同時に実行していることがわかります。
11-28 00:00:09.593: [ExecutorActivity#newCachedThreadPoolTest:140]
11-28 00:00:09.603: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27829
11-28 00:00:09.623: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:00:09.623: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27830
11-28 00:00:09.633: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-28 00:00:09.643: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27831
11-28 00:00:09.643: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-28 00:00:09.653: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27832
11-28 00:00:09.653: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-28 00:00:10.614: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:00:10.634: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-28 00:00:10.634: [ExecutorActivity$ExecutorRunnable#run:306]C: end
11-28 00:00:10.654: [ExecutorActivity$ExecutorRunnable#run:306]D: end

Executors.newScheduledThreadPool(int);

public void newScheduledThreadPoolTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
    executorService.schedule(new ExecutorRunnable("A", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("B", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("C", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("D", 1), 1, TimeUnit.SECONDS);
}
引数のスレッド数で実行します。今回は2スレッドで実行します。
実行タイミングを設定できますが同じタイミングを設定した場合は実行順が前後することがあります。
というか実行タイミング依存なので実行順は追加順に依存しないということだと思います。
設定のスレッド数に達したら待たされていることがわかります。
11-28 00:04:23.701: [ExecutorActivity#newScheduledThreadPoolTest:156]
11-28 00:04:24.712: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27833
11-28 00:04:24.722: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27834
11-28 00:04:24.722: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:04:24.722: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-28 00:04:25.733: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-28 00:04:25.733: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:04:25.743: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27834
11-28 00:04:25.753: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27833
11-28 00:04:25.753: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-28 00:04:25.753: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-28 00:04:26.754: [ExecutorActivity$ExecutorRunnable#run:306]D: end
11-28 00:04:26.754: [ExecutorActivity$ExecutorRunnable#run:306]C: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#schedule(Runnable, long, TimeUnit) の実行タイミングが被らないパターン

public void newSingleThreadScheduledExecutorTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.schedule(new ExecutorRunnable("A", 1), 8, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("B", 1), 4, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("C", 1), 0, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("D", 1), 12, TimeUnit.SECONDS);
}
SingleThread なのでタスクをいくつ追加しても一つのスレッドで実行します。
設定した実行タイミングの順で実行されていることがわかるようにしました。
11-28 00:10:40.248: [ExecutorActivity#newSingleThreadScheduledExecutorTest:172]
11-28 00:10:40.278: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27847
11-28 00:10:40.278: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-28 00:10:41.289: [ExecutorActivity$ExecutorRunnable#run:306]C: end
11-28 00:10:44.262: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27847
11-28 00:10:44.262: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-28 00:10:45.273: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-28 00:10:48.256: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27847
11-28 00:10:48.266: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:10:49.267: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:10:52.260: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27847
11-28 00:10:52.270: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-28 00:10:53.271: [ExecutorActivity$ExecutorRunnable#run:306]D: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#schedule(Runnable, long, TimeUnit) の実行タイミングが被るパターン

public void newSingleThreadScheduledExecutorDuringExecutionTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.schedule(new ExecutorRunnable("A", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("B", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("C", 1), 1, TimeUnit.SECONDS);
    executorService.schedule(new ExecutorRunnable("D", 1), 1, TimeUnit.SECONDS);
}
SingleThread なのでタスクをいくつ追加しても一つのスレッドで実行します。
実行タイミングがかぶったら待たされます。
11-28 00:14:52.637: [ExecutorActivity#newSingleThreadScheduledExecutorDuringExecutionTest:188]
11-28 00:14:53.648: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27848
11-28 00:14:53.648: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:14:54.659: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:14:54.669: [ExecutorActivity$ExecutorRunnable#run:299]B: ThreadId: 27848
11-28 00:14:54.669: [ExecutorActivity$ExecutorRunnable#run:300]B: start
11-28 00:14:55.680: [ExecutorActivity$ExecutorRunnable#run:306]B: end
11-28 00:14:55.690: [ExecutorActivity$ExecutorRunnable#run:299]C: ThreadId: 27848
11-28 00:14:55.690: [ExecutorActivity$ExecutorRunnable#run:300]C: start
11-28 00:14:56.701: [ExecutorActivity$ExecutorRunnable#run:306]C: end
11-28 00:14:56.701: [ExecutorActivity$ExecutorRunnable#run:299]D: ThreadId: 27848
11-28 00:14:56.711: [ExecutorActivity$ExecutorRunnable#run:300]D: start
11-28 00:14:57.712: [ExecutorActivity$ExecutorRunnable#run:306]D: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit) の実行タイミングを過ぎないパターン

public void newSingleThreadScheduledExecutorAtFixedRateTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleAtFixedRate(new ExecutorRunnable("A", 1), 1, 2, TimeUnit.SECONDS);
    shutdown(executorService); // 8秒後に終了します
}
一つのスレッドで実行します。実行タイミングを設定できます。繰り返し実行でき、実行間隔を設定できます。
実行間隔は実行開始から次の実行開始までの時間です。
実行間隔 が 2 秒で、実行 1 秒なので終了してから 1 秒で実行されます。
11-28 00:19:44.952: [ExecutorActivity#newSingleThreadScheduledExecutorAtFixedRateTest:205]
11-28 00:19:45.963: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27850
11-28 00:19:45.963: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:19:46.974: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:19:47.965: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27850
11-28 00:19:47.965: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:19:48.966: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:19:49.967: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27850
11-28 00:19:49.967: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:19:50.968: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:19:51.969: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27850
11-28 00:19:51.969: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:19:52.970: [ExecutorActivity$1#run:273]shutdown
11-28 00:19:52.980: [ExecutorActivity$ExecutorRunnable#run:306]A: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit) の実行タイミングを過ぎるパターン

public void newSingleThreadScheduledExecutorAtFixedRateDuringExecutionTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleAtFixedRate(new ExecutorRunnable("A", 3), 1, 2, TimeUnit.SECONDS);
    shutdown(executorService); // 8秒後に終了します
}
一つのスレッドで実行します。実行タイミングを設定できます。繰り返し実行でき、実行間隔を設定できます。
実行間隔は実行開始から次の実行開始までの時間です。
実行に 3 秒かかるのに実行間隔を 2 秒にした場合、次の実行開始タイミングは過ぎているのですぐに実行します。
11-28 00:23:59.431: [ExecutorActivity#newSingleThreadScheduledExecutorAtFixedRateDuringExecutionTest:221]
11-28 00:24:00.442: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27851
11-28 00:24:00.442: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:24:03.444: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:24:03.454: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27851
11-28 00:24:03.454: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:24:06.467: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:24:06.477: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27851
11-28 00:24:06.477: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:24:07.438: [ExecutorActivity$1#run:273]shutdown
11-28 00:24:08.449: [ExecutorActivity$1#run:276]shutdownNow
11-28 00:24:08.499: [ExecutorActivity$ExecutorRunnable#run:306]A: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit) の実行タイミングを被らないパターン

public void newSingleThreadScheduledExecutorWithFixedDelayTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleWithFixedDelay(new ExecutorRunnable("A", 1), 1, 2, TimeUnit.SECONDS);
    shutdown(executorService); // 8秒後に終了します
}
一つのスレッドで実行します。実行タイミングを設定できます。繰り返し実行でき、実行間隔を設定できます。
実行間隔は実行終了から次の実行開始までの時間です。
1 秒のタスクを実行終了してから 2 秒後に次の実行が開始されていることがわかります。
11-28 00:31:25.436: [ExecutorActivity#newSingleThreadScheduledExecutorWithFixedDelayTest:236]
11-28 00:31:26.447: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27852
11-28 00:31:26.447: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:31:27.458: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:31:29.470: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27852
11-28 00:31:29.470: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:31:30.481: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:31:32.483: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27852
11-28 00:31:32.483: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:31:33.443: [ExecutorActivity$1#run:273]shutdown
11-28 00:31:33.494: [ExecutorActivity$ExecutorRunnable#run:306]A: end

Executors.newSingleThreadScheduledExecutor(); で ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit) の実行タイミングが被るパターン

public void newSingleThreadScheduledExecutorWithFixedDelayDuringExecutionTest(){
    LogUtils.d();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleWithFixedDelay(new ExecutorRunnable("A", 3), 1, 2, TimeUnit.SECONDS);
    shutdown(executorService);
}
一つのスレッドで実行します。実行タイミングを設定できます。繰り返し実行でき、実行間隔を設定できます。
実行間隔は実行終了から次の実行開始までの時間なので実行タイミングが被ることがないです。
3 秒のタスクを実行終了してから 2 秒後に次の実行が開始されていることがわかります。
11-28 00:34:05.822: [ExecutorActivity#newSingleThreadScheduledExecutorWithFixedDelayDuringExecutionTest:252]
11-28 00:34:06.833: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27853
11-28 00:34:06.833: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:34:09.846: [ExecutorActivity$ExecutorRunnable#run:306]A: end
11-28 00:34:11.848: [ExecutorActivity$ExecutorRunnable#run:299]A: ThreadId: 27853
11-28 00:34:11.858: [ExecutorActivity$ExecutorRunnable#run:300]A: start
11-28 00:34:13.840: [ExecutorActivity$1#run:273]shutdown
11-28 00:34:14.851: [ExecutorActivity$1#run:276]shutdownNow
11-28 00:34:14.901: [ExecutorActivity$ExecutorRunnable#run:306]A: end

おまけ

上の ScheduledExecutorService#scheduleAtFixedRate と
ScheduledExecutorService#scheduleWithFixedDelay ではタスクを一つしか与えていないが、
これをそれぞれもう一つ initialDelay を1秒ずらして追加すると
どちらも実行終了を待たされて次の実行タイミングが来てすぐに実行するようになってしまいます。

Executors.newScheduledThreadPool(int); ではどうなる?

上の ScheduledExecutorService#scheduleAtFixedRate と
ScheduledExecutorService#scheduleWithFixedDelay で ExecutorService の生成を
Executors.newScheduledThreadPool(int); で行った場合は、
繰り返される同一のタスクは一つのスレッドで固定で、タスクの追加ごとにスレッドが分かれるようになります。
実行タイミングが過ぎたり、被ったりすると実行タイミングが来てすぐに実行するようになってしまいます。
ちゃんと等間隔で実行したかったら一つの ExecutorService に一つのタスクが良いかと思います。

ExecutorService の終了の仕方

try{
    LogUtils.d("shutdown");
    executorService.shutdown();
    if(!executorService.awaitTermination(1, TimeUnit.SECONDS)){
        LogUtils.d("shutdownNow");
        executorService.shutdownNow();
    }
}catch(InterruptedException e){
    e.printStackTrace();
    LogUtils.d("shutdownNow: " + e.getMessage());
    executorService.shutdownNow();
}
ExecutorService#shutdown で終了命令を出して新規タスクの追加の禁止して、
実行中のタスクが終了せずに ExecutorService#awaitTermination でタイムアウト時間を過ぎたら
ExecutorService#shutdownNow で実行中のタスクをキャンセルするといった流れです。
shutdownNow が呼ばれると ExecutorRunnable の sleep で InterruptedException が投げられますが
ExecutorService#shutdownNow が直接的にタスクの実行を強制終了するわけではないようです。

まとめ

長くなりましたが ExecutorService の使い方をまとめました。
ExecutorService はかなり強力なマルチスレッドの実行キューの便利クラスなのでぜひ使いこなしたいですね!
2013/11/15

[Java]マルチスレッドでの排他処理を行うsynchronizedを理解する

今までマルチスレッドプログラミングというものをしてこなかったので
排他処理とか synchronized とかなにそれオイシイの状態だったので
理解するために簡単なサンプルを Android で作ってみました。

参考
Javaスレッドメモ(Hishidama's Java thread Memo)

サンプルコードは以下にあります。
SynchronizedActivity.java | wada811/AndroidLibrary@wada811
AndroidLibrary ってなってるけどコレは Android 関係ないです。

メソッド修飾の synchronized

クラスメソッド

/**
 * クラスメソッドを synchronized にした場合のテスト実行メソッド
 */
public void syncClassMethodExecute(){
    PreferenceUtils.putString(this, SyncClassMethodExecuter.KEY, null);
    new Thread(new SyncClassMethodExecutorRunnable("A")).start();
    new Thread(new SyncClassMethodExecutorRunnable("B")).start();
    new Thread(new SyncClassMethodExecutorRunnable("C")).start();
}

public class SyncClassMethodExecutorRunnable implements Runnable {
    String threadName;

    public SyncClassMethodExecutorRunnable(String threadName) {
        this.threadName = threadName;
    }

    @Override
    public void run(){
        SyncClassMethodExecuter.execute(self, threadName);
    }
}

/**
 * クラスメソッドを synchronized にした場合のテストクラス
 */
public static class SyncClassMethodExecuter {

    public static final String KEY = SyncClassMethodExecuter.class.getSimpleName();

    public static final synchronized void execute(Context context, String threadName){
        String lastThreadName = PreferenceUtils.getString(context, KEY, null);
        if(lastThreadName != null){
            LogUtils.d(threadName + ": do nothing. " + lastThreadName + " is executed.");
        }else{
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            LogUtils.d(threadName + ": execute");
            PreferenceUtils.putString(context, KEY, threadName);
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
synchronized にしてるから1秒待って A が実行されたら1秒後に B, C と実行されていて
ブロックされているのが実行ログからわかります。
11-14 22:57:39.801: [SynchronizedActivity#syncClassMethodExecute:115]
11-14 22:57:40.872: [SynchronizedActivity$SyncClassMethodExecutor#execute:152]A: execute
11-14 22:57:41.933: [SynchronizedActivity$SyncClassMethodExecutor#execute:145]B: do nothing. A is executed.
11-14 22:57:41.943: [SynchronizedActivity$SyncClassMethodExecutor#execute:145]C: do nothing. A is executed.
synchronized をとれば A, B, C 全部が execute を通ることも確認できます。

インスタンスメソッド

/**
 * インスタンスメソッドを synchronized にした場合のテスト実行メソッド
 */
public void syncThisInstanceMethodExecute(){
    LogUtils.d();
    SyncThisInstanceMethodExecutor executor = new SyncThisInstanceMethodExecutor();
    new Thread(new SyncThisInstanceMethodExecutorRunnable(executor, "A")).start();
    new Thread(new SyncThisInstanceMethodExecutorRunnable(executor, "B")).start();
    new Thread(new SyncThisInstanceMethodExecutorRunnable(executor, "C")).start();
}

public class SyncThisInstanceMethodExecutorRunnable implements Runnable {
    private SyncThisInstanceMethodExecutor mExecutor;
    private String                         mThreadNmae;

    public SyncThisInstanceMethodExecutorRunnable(SyncThisInstanceMethodExecutor executor, String threadNmae) {
        mExecutor = executor;
        mThreadNmae = threadNmae;
    }

    @Override
    public void run(){
        mExecutor.execute(mThreadNmae);
    }

}

/**
 * インスタンスメソッドを synchronized にした場合のテストクラス
 */
public class SyncThisInstanceMethodExecutor {
    private int mCount = 0;

    public synchronized void execute(String threadName){
        if(mCount == N){
            LogUtils.d(threadName + ": do nothing");
        }else{
            for(int i = 0; i < N; i++){
                LogUtils.d(threadName + ": " + ++mCount);
            }
            try{
                TimeUnit.SECONDS.sleep(1);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }
}
インスタンスメソッドの synchronized はメソッドボディを synchronized(this){ 〜 } で囲ったのと
同じ動きをするらしいので SyncThisInstanceMethodExecutor という名前にしました。
参考: Javaスレッドメモ(Hishidama's Java thread Memo)
コレもバッチリ A の実行が終わるのを待たされているのが実行ログから分かります。
[SynchronizedActivity#syncThisInstanceMethodExecute:219]
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 1
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 2
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 3
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 4
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 5
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 6
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 7
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 8
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 9
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:253]A: 10
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:250]B: do nothing
[SynchronizedActivity$SyncThisInstanceMethodExecutor#execute:250]C: do nothing

ロックオブジェクトを synchronized

/**
 * インスタンスメソッドでロックオブジェクトを synchronized した場合のテスト実行メソッド
 */
public void syncLockInstanceMethodExecute(){
    LogUtils.d();
    SyncLockInstanceMethodExecutor executor = new SyncLockInstanceMethodExecutor();
    new Thread(new SyncLockInstanceMethodExecutorRunnable(executor, "A")).start();
    new Thread(new SyncLockInstanceMethodExecutorRunnable(executor, "B")).start();
    new Thread(new SyncLockInstanceMethodExecutorRunnable(executor, "C")).start();
}

public class SyncLockInstanceMethodExecutorRunnable implements Runnable {
    private SyncLockInstanceMethodExecutor mExecutor;
    private String                         mThreadNmae;

    public SyncLockInstanceMethodExecutorRunnable(SyncLockInstanceMethodExecutor executor, String threadNmae) {
        mExecutor = executor;
        mThreadNmae = threadNmae;
    }

    @Override
    public void run(){
        mExecutor.execute(mThreadNmae);
    }

}

/**
 * インスタンスメソッドでロックオブジェクトを synchronized した場合のテストクラス
 */
public class SyncLockInstanceMethodExecutor {
    private final Object lock   = new Object();
    private int          mCount = 0;

    public void execute(String threadName){
        synchronized(lock){
            if(mCount == N){
                LogUtils.d(threadName + ": do nothing");
            }else{
                for(int i = 0; i < N; i++){
                    LogUtils.d(threadName + ": " + ++mCount);
                }
                try{
                    TimeUnit.SECONDS.sleep(1);
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
SyncLockInstanceMethodExecutor は SyncThisInstanceMethodExecutor とほとんど同じだけど
メソッド修飾の synchronized じゃなくて synchronized 文になってオブジェクトをロックしています。
SyncThis と同じなので実行ログは省略します。
StackOverflow でこっちの方法を推奨している回答がありました。
synchronization - How to synchronize or lock upon variables in Java? - Stack Overflow
blog.pasberth.com: Javaのsynchronizedってなにをブロックしているの?のコメントでもあるように
synchronized(this) は同一インスタンスでしか排他処理ができないので
SyncLockInstanceMethodExecutor を複数インスタンス生成されたら排他制御できなくなります。
なので以下のようにグローバルなオブジェクトを synchronized すると別インスタンスでも排他制御できます。
public static final Object LOCK = new Object();

public void syncGrobalLockExecute(){
    LogUtils.d();
    new Thread(new SyncGrobalLockExecutorRunnable(new SyncGrobalLockExecutor(), "A")).start();
    new Thread(new SyncGrobalLockExecutorRunnable(new SyncGrobalLockExecutor(), "B")).start();
    new Thread(new SyncGrobalLockExecutorRunnable(new SyncGrobalLockExecutor(), "C")).start();
}

public class SyncGrobalLockExecutorRunnable implements Runnable {
    private SyncGrobalLockExecutor mExecutor;
    private String                 mThreadNmae;

    public SyncGrobalLockExecutorRunnable(SyncGrobalLockExecutor executor, String threadNmae) {
        mExecutor = executor;
        mThreadNmae = threadNmae;
    }

    @Override
    public void run(){
        mExecutor.execute1(mThreadNmae);
        mExecutor.execute2(mThreadNmae);
        mExecutor.execute3(mThreadNmae);
    }

}

public class SyncGrobalLockExecutor {
    private int mCount = 0;

    public void execute1(String threadName){
        synchronized(LOCK){
            for(int i = 0; i < N; i++){
                LogUtils.d(threadName + "[1]: " + ++mCount);
            }
        }
    }

    public void execute2(String threadName){
        synchronized(LOCK){
            for(int i = 0; i < N; i++){
                LogUtils.d(threadName + "[2]: " + ++mCount);
            }
        }
    }

    public void execute3(String threadName){
        synchronized(LOCK){
            for(int i = 0; i < N; i++){
                LogUtils.d(threadName + "[3]: " + ++mCount);
            }
        }
    }
}
同じ LOCK に対する排他制御なので execute1, execute2, execute3 同士も排他制御されます。
インスタンスごとに呼ぶメソッドを変えてあげればわかりやすいです。
SyncGrobalLockExecutor はサンプルに入ってないので適当に書き換えて試してみて下さい。

synchronized を使いこなせればプログラミングの幅が広がりそうですね。
長くなったのでこのへんで。
2013/08/18

[Eclipse][Java]UTF-8で文字化けしないJavadocを生成する

「File > Export…」を選択し、「Java > Javadoc」を選択します。
Javadoc を生成したいプロジェクトを選択し、次へ進みます。

次の画面はよくわからないのでそのままで次へ進みます。

下の画像のように Javadoc 追加オプションに以下を追加します。
-encoding UTF-8
-charset UTF-8

Finish で 文字化けしていない Javadoc が生成されると思います。
参考
クラウドサービスプラットフォーム Cosminexus:EclipseからJavadocを生成するには?:ソフトウェア:日立
comscom@Wiki - Eclipse/Javadoc/Javadocの日本語が文字化けしちゃうの。
2013/05/07

[Eclipse]コンテンツアシストのトリガーを変更して爆速コーディング

Eclipse > Preference > XML > XML Files > Editor > Content Assist から
Auto Activation の Auto Activation delay (ms) (※補完プロンプト表示ディレイ時間)と
Prompt when these characters are inserted (※補完プロンプト表示トリガー) を
変更します。
ディレイ時間を短くすればするほど爆速ですが思考が付いていかない気がします。
ネタ帳 A.B.C: Android Layout XMLのコーディングを快適にする方法を参考に
トリガーを以下のように設定しました。
<=:._@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ


Java でも Eclipse > Preference > Java > Editor > Content Assist から
Auto Activation の項目を同様に変更することで設定できます。
参考: Eclipseの補完設定をカスタマイズして爆速コーディング - ser1zw's blog
しかしプロンプトが出てからスペースを押すと補完を入力してスペースが入ってしまうので微妙かもしれません。
2012/08/09

[書評]日経ソフトウエア 2012年 01月号

日経ソフトウエア 2012年 01月号 [雑誌]
日経BP社
発売日:2011-11-24
ブクログでレビューを見る»
Android4.0の注目機能の解説、Java7とJava8の新機能の解説、
Androidアプリ設計法、Windows 8のMetroスタイルアプリ、Xcode4使い方入門など。
付録はWindows 7のガイドブック。

凄い今更感あるけど今年から日経ソフトウエアを購読することにしたので
チマチマ読んで記事書いとくことにした。まずは1月号から。

日経ソフトウエア ダウンロード - 2012年:ITpro

@vvakameさんのAndroidAndroid4.0特別レポート

Fragmentについて。Android4.0でPhoneとTabletの両対応が楽になってるらしい。そのうち本気出して対応する。
Android Beamについて。NFC(近距離無線通信)による端末間のやり取りを簡素化したものらしい。
NFCはAndroid2.3からあるからAndroid2.3 Only Hacksを読むといいよ!ってステマが見えた。
ソフトウエアキーについて。ハードウエアキーが廃止された。ソフトウエアキーの入った部分をシステムバーという。
メニューキーは廃止され、アクションバーという画面上部のところに吸収された。メニューがあったら表示される。
他にも色々書いてあった。個人的にカレンダーAPI使って何か作りたいから気になってる。

Java新時代へ Java7, 8の新機能

Java7はswicth文の条件にString型が使用可能になっていたり、
複数例外のマルチキャッチやクローズ処理の自動実行など便利そうな進化をするらしい。
ファイルのコピーや移動なども簡単になるみたい。
Java8はクロージャが目玉かも?マルチコアで並列処理するのにクロージャを利用するのだとか。

Androidアプリ設計法

Galleryの使い方と画像の扱いが参考になりそうだった。結構コード載ってて良い感じ。

Windows 8 と Visual Studio 11 Metroアプリ開発

商標獲得で初歩的なミス? マイクロソフト、Windows 8から「Metro」の名称を排除へ|Microsoftウォッチ|トピックス|Computerworld
こんなことがあってもはやMetroじゃなくなるらしいけども。
簡単にWindows 8の使い方を説明したあと、Visual Studio 11でMetroアプリを開発の流れ。
HTML +Javascriptで作れるということで、僕がJavascriptを学びたい理由の一つである。

Xcode 4.2の使い方入門

結構詳しく書いてあって参考になる。できればキーボードショートカットも欲しかったけど以下があるので大丈夫だった。
好評のXcodeチートシート、MacBook Air 11サイズを作成しました | DOTAPON Blog

付録: Windows 7ガイドブック

う~ん、って感じの設定があってどうも。対象読者のレベルが高いのか低いのかよくわからない。
付録レベルだし期待するほどのものでもないような気がする。

新しさを軸に話題を知るというのもいいな。雑多な感じの記事も書きやすい。
日経 ソフトウエア 2012年 01月号 [雑誌]
日経 ソフトウエア 2012年 01月号 [雑誌]
2012/07/15

[Android]twiccaプラグインを作ってみた ツイート編集編

関連:[Android]twiccaプラグインを作ってみた ツイート表示アクション編 | DevAchieve
関連:[Android]twiccaプラグインを作ってみた 設定アクション編 | DevAchieve

入力中のツイートのテキストを受け取って編集して twicca に返すことができる。
<intent-filter>
    <action android:name="jp.r246.twicca.ACTION_EDIT_TWEET" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
いい加減書くこともないので抜粋。
if(action.equals("jp.r246.twicca.ACTION_EDIT_TWEET")){
    String text = intent.getStringExtra(Intent.EXTRA_TEXT);
    intent.removeExtra("prefix");
    intent.removeExtra("suffix");
    intent.removeExtra("user_input");
    intent.putExtra(Intent.EXTRA_TEXT, edit(text));
    setResult(RESULT_OK, intent);
    finish();
}
受け取った Intent と返す Intent で Extras に共通しているところがある。
受け取ってセットし直すのもアホらしいので調べたら remove できた。コレは知らなかった。

[Android]twiccaプラグインを作ってみた 設定アクション編

せっかくなので設定も追加してみた。
関連:[Android]twiccaプラグインを作ってみた ツイート表示アクション編 | DevAchieve

設定用に PreferenceActivity を追加する。
PreferenceActivity は Android 3.0 以上からは Prefarence Fragment に置き換えられるらしい。
そして Android 3.0 未満は Compatibility Package というのを使って対応するらしい。
Support Library | Android Developersにある。
でもtwiccaプラグインの一つの項目しか無い設定画面1ページにそこまでするのが面倒大げさな気がする。
いや、はい。Xperia Arc(Android 2.3以上にアップデート出来ない宿命を背負った端末)から変えたら対応するよ…。

ということで Androidmanifest.xml に Intent を受け取れるように記述する。
設定アクション | Developers | twicca - Yet another Twitter client for Android.
<activity
    android:name=".QuoteTweetSettings"
    android:label="@string/app_name"
    >
    <intent-filter>
        <action android:name="jp.r246.twicca.ACTION_PLUGIN_SETTINGS" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
QuoteTweetSettings.java で設定画面用XMLを onCreate() で読み込んで onStart() で色々する。
@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.pref);
}

@Override
protected void onStart(){
    super.onStart();

    final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
    CheckBoxPreference check = (CheckBoxPreference)getPreferenceScreen().findPreference(getString(R.string.key));
    check.setChecked(sp.getBoolean(check.getKey(), false));
    check.setOnPreferenceChangeListener(new OnPreferenceChangeListener(){
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue){
            if(preference.getClass() == CheckBoxPreference.class){
                if(preference.getKey().equals(getString(R.string.key))){
                    sp.edit().putBoolean(preference.getKey(), (Boolean)newValue).commit();
                    return true;
                }
            }
            return false;
        }
    });
}
sp を final にしておくと OnPreferenceChangeListener() 内で使えるから便利。
設定項目が多かったら無名インナークラスで書くのはやめたほうがよさそう。
クラスの比較はなんかできたのでやってみただけ。意味は無い。と思う。
複数の CheckBoxPreference の onPreferenceChange() を一回の記述で済ませられそう。
そのためにはキーを string.xml で string-array で保存すればいけるのかもしれない。

addPreferencesFromResource(R.xml.pref);で読み込んだやつ。
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
 android:key="@string/key"
 android:title="@string/title"
 android:summaryOn="@string/on"
 android:summaryOff="@string/off"
 android:defaultValue="false"
 />
</PreferenceScreen>
ハードコーディングすると変更時に死ねるので全部 string.xml にぶち込む。
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">QuoteTweet プラグイン for twicca</string>
    <string name="key">reply</string>
    <string name="title">リプライを入れる</string>
    <string name="on">QT @screen_name https://twitter.com/</string>
    <string name="off">QT https://twitter.com/</string>
</resources>
2012/07/14

[Android]twiccaプラグインを作ってみた ツイート表示アクション編

twiccaを使っているのでせっかくだからtwiccaプラグイン作りたいなぁ、ということで作ってみました。

ツイート表示アクション | Developers | twicca - Yet another Twitter client for Android.
<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
コイツを消して、
<intent-filter>
    <action android:name="jp.r246.twicca.ACTION_SHOW_TWEET" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>
これに書き換える。

ついでにActivityを開いて何をするでもないので非表示にしといた。[Android]Activityを非表示にする | DevAchieve

@Override
protected void onStart(){
    super.onStart();

    final Intent intent = getIntent();
    if(intent == null){
        setResult(Activity.RESULT_CANCELED);
        finish();
    }
    final String action = intent.getAction();
    if(action.equals("jp.r246.twicca.ACTION_SHOW_TWEET")){
        final String statusId = intent.getStringExtra("id");
        final String screenName = intent.getStringExtra("user_screen_name");
        final String tweet = " QT https://twitter.com/" + screenName + "/status/" + statusId;
        tweet(this, tweet);
        setResult(RESULT_OK);
        finish();
    }else{
        setResult(RESULT_CANCELED);
        finish();
    }
}
忘れたけどgetIntent()はonStart()でやるべきって話を聞いたような気がする。詳しい話は忘れた。
後はコイツに投げてやるだけ↓
ツイート画面をアプリ/プラグインから呼び出す | Developers | twicca - Yet another Twitter client for Android.

GitHubにあげたー
wada811/QuoteTweetPlugin4twicca · GitHub
GitHubでTwicca Pluginで検索すると結構出てくるから参考になるよ。

[Android]Activityを非表示にする

アプリを起動するけども表示はさせない場合はコード中の setContentView の記述を削除すればいい。
しかし、これだけでは初回起動時に一瞬だけ起動アニメーションが見えてしまう。

表示させないようにするにはAndroidManifest.xmlの<application>タグか<activity>タグで以下のどちらかを記述する。
android:theme="@android:style/Theme.Translucent" // タイトルバーの表示あり
android:theme="@android:style/Theme.Translucent.NoTitleBar" // タイトルバーの表示なし
改訂2版 Android SDK逆引きハンドブック
改訂2版 Android SDK逆引きハンドブック

タグ(RSS)