Serviceのログどうやるのがスマートなのん †
今日の予定がキャンセルになったので久しぶりにAndroid触ってた。Twitterのストリームをリアルタイム表示するアプリを作ってUST中でもハッシュタグでのつぶやきをリアルタイムで見られるようにしたい。
今回ServiceをPlain Javaの別プロジェクトとして作ってからAndroidに結合した。理由は、このストリームを読み込んでTweetエンティティを作成するServiceは汎用で使える可能性があるのでAndroid専用にしたくない、それとAndroidプロジェクトにするとJUnitの実行がとてもめんどうになるの2点。単体テストまではこれで良かったんだけど、Androidに組み込んだ後の結合時にService内のログを取りたいと思った時に結構めんどいことになることに気がついた。AndroidでLogを取るには android.util.Log が用意されているんだけど、ServiceはPlain Javaで書いているのでこれは使うべきでない。なぜなら android.util.Log をService内で使ったとたん、このServiceはAndroid専用になってしまうから。めんどくさいけど、しょうがないからログ出力用コールバックインターフェイスを定義して、Service作成時にこれも一緒に渡すことで逃げた。厳密にドメインを分けるとこうなるよね。たかがログの出力ってだけなのにこんな大げさな事になってしまうのはもっと良い解決方法はないものかのう。
// 抜粋
public final class TweetStreamServiceFactory {
public interface LogAppender {
void notice(final String message);
void notice(final Throwable e);
}
public interface TweetHandler {
void notice(final Tweet tweet);
}
public static TweetStreamService create(
final TweetHandler handler,
final String user,
final String pass,
final String keyword,
final LogAppender logAppender) {
return new TweetStreamServiceImpl(handler, user, pass, keyword, logAppender);
}
}
Android側から呼び出す時はこんな感じになる。これで1文。これはひどい^0^; 次のお前の台詞は「Scalaならもっと短くなるな」だ。高階関数ェ、お前はオレにとっての新たな光だ。
final TweetStreamService service = TweetStreamServiceFactory.create(new TweetHandler() {
@Override public void notice(final Tweet tweet) {
handler.post(new Runnable() {
@Override
public void run() {
Log.d("tweetStreamReader", "arrived");
list.add(0, tweet);
while (list.size() > 100) {
list.remove(list.size()-1);
}
onContentChanged();
}
});
}
}, user, pass, keyword, new LogAppender(){
@Override public void notice(final String message) {
Log.d(tag, message);
}
@Override public void notice(final Throwable e) {
Log.d(tag, "", e);
}
});
Android+Log4jも思いついたけど、少し調べてみたら苦労しそうな印象だな。
関係ないけど、昔作ったAIで動くオセロをGitHubに登録してみたよ。 https://github.com/almirage/AIOthello