Twitterクライアント製作記その3
ふぁぼった時に星を付けれるようになった.
どうやら,公式RTされてきたものに対してのtwitter4j.Status#isFavorited()はなんかちょっと特殊だった.
Twitter#createFavorite(long id)で指定されたIDのツイートをふぁぼるんだけど,いくらふぁぼっても公式RTの場合は
getHomeTimeline()でそのツイートを取得しなおしても,status,retweetedStatusどちらもisFavorited()でfalseが返ってくるので,どうやって公式RTをふぁぼったときに星を付けられるのかわからなかったけど解決できたのでメモ.
Twitter#createFavorite(long id)は戻り値としてtwitter4j.Statusが返ってくるので,返ってきたstatusを使って処理すれば良い.
ふぁぼに成功した場合,返ってきたstatusと,retweetedStatusはisFavorited()でどちらもtrueを返す.
ArrayAdapterの中にある元のツイートの場所を,mAdapter.position(oldStatus);でもして引っ張ってきて,remove(oldStatus)して,insert(position,newStatus);とすればよい.
星をつける部分は,ArrayAdapter
抜粋
twitter4j.Status oldStatus, newStatus; twitter4j.Twitter mTwitter; //oldStatusはなんとかして持ってくる //mTwitterはなんとかしてfactoryからインスタンスを作る try { newStatus = mTwitter.createFavorite(status.getId()); } catch (TwitterException e) { e.printStackTrace(); } if (newStatus != null) { int pos = mAdapter.getPosition(oldStatus);//元のツイートの位置を得る mAdapter.remove(oldStatus);//消す mAdapter.insert(newStatus, pos);//挿入する mAdapter.notifyDatasetChanged();//ListViewに通知してViewの更新 }
カスタムArrayAdapter(抜粋)
public class TweetStatusAdapter extends ArrayAdapter<twitter4j.Status> { private static LayoutInflater mInflater; public TweetStatusAdapter(Context context) { super(context, android.R.layout.simple_list_item_1); mInflater = (LayoutInflater) context .getSystemService(Activity.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { Status item = getItem(position); if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item_tweet, null); } //他にも色々やるけどね. ImageView favIcon = (ImageView)convertView.findViewById(R.id.fav_icon); if (item.isFavorited()){ favicon.setVisibility(View.VISIBLE); } else { favicon.setVisibility(View.GONE); } return convertView; } }
それにしても,公式RTをふぁぼってもgetHomeTimeline()やgetMentionsTimeline()で得られるstatusがisFavorited()でfalse返すってTwitterさんなんでなのよ…
今日できたこと
- リストの情報(id, name)を保存して,毎回起動時にリスト情報を取得するために通信しないようにした.
- 通信する必要が有るときは出来る限りAsyncTaskを使用するようにした(Android3.0以上だと,メインスレッドから通信するとNetworkOnMainThreadExceptionという例外を投げる)
- Android4.2でもOAuthコールバック時にちゃんと起動するようになった
- リストを選択して表示
- 会話を表示
Twitterクライアント製作記その2
出来たこと
- リストビューが空のときに表示を変えた(ListView#setEmptyView())
- リストビューの一番下が見えた時にツイートを読み込むようにした(ListView#setFooterView())
- 認証アカウントの全リストのフラグメントを作成&ViewPagerで表示.スワイプで移動するのは辛い.
- グラデーションよりものっぺりした方がナウいのでタイルっぽいデザインに,背景をグレーに,他の色はだいたいGoogleのDeveloperサイトに載ってる色にした.
- 取得時すでにふぁぼっていたツイートには星をつけた.(リツイートだった場合はなぜか判別できないため星を付けれない)
- お気に入りツイート一覧を表示
ツイートを取得して表示するための基底クラス(抽象クラス)を作成し,これを継承したクラスでリストだったりメンションだったりタイムラインだったりの動作を実装することで,かなり楽に機能を実装できるようになった.
ふぁぼった時,リツイートしたときに,そのツイートにアイコンを付けるようにしたいんだけど,色々スパゲティ状態で辛い.
そして何より,リツイートをふぁぼっていても,リツイートとして表示しているときはなぜか判別が出来ない.
status.isFavorited()でも,status.getRetweetStatus().isFavorited()でもfalseという謎.
getFavorites()で得られたツイートは,status.isFavorites()はtrueになるのになぜなんだ…!
会話を表示するアクティビティと,ユーザーの情報を表示するアクティビティまで出来たらコードごと公開するよ.
Twitterクライアントっぽいもの製作記 その1
Shooting Starっぽいクライアントが作りたいんだ…!ただ,それだけっ…!
今日までにできていること
- 認証
- HomeTimelineの取得,表示
- MentionsTimelineの取得,表示
- Statusのアップデート
- 引っ張って更新,引っ張って古いツイートの取得
- タイムラインの色分け+グラデーション
- リプライ,リツイート,ふぁぼ,本文に含まれているリンクにジャンプ
はやくリストを選択して表示できるようにしたい.ListViewが空のときはタップして更新できるようにしたい.
AndroidNDKで作成されるネイティブコードの最適化
APP_CFLAGS := -O2 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -fPIC -march=armv7-a
Application.mkに上記の内容を追記すると,浮動小数点演算が高速化される.
- O2は言わずもがなの最適化オプション
- mcpu=cortex-a8でCPUの指定
- fPICで静的ライブラリの最適化
- march=armv7-aでアーキテクチャの指定
かな.間違ってるかも.
入力ノード数3,隠れノード数10*2層,出力ノード数1のニューラルネットをバックプロパゲーションで,6種類の教師信号を50000回学習するのにかかった時間が,最適化なしは約20秒,最適化ありだと約4秒になった.すごい.
参考
EclipseでデバッグするときSTLコンテナの中身を整形して表示
C++でプログラミングをしていて,デバッグするときにgdbを使えばいいんですけど使い方がいまいちよくわからないのでEclipseを使ってデバッグしたらGUIだし見やすくて操作もしやすくていいかなと思っていたらとんでもない罠があった.
STLコンテナの中身がカオス!
絶対綺麗に表示できるようなプラグイン的Somethingがあるはずだと思い調査.
一応公式に書いてあった http://wiki.eclipse.org/CDT/User/FAQ#How_can_I_inspect_the_contents_of_STL_containers.3F
GDB用のSTLサポートライブラリ的なものをダウンロード
svn co svn://gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python
または,http://sourceware.org/gdb/wiki/STLSupport からSTLSupportToolを適当なディレクトリにダウンロードして展開
gdbinitファイルを適当な場所に作成
python import sys sys.path.insert(0, '/home/maude/gdb_printers/python') from libstdcxx.v6.printers import register_libstdcxx_printers register_libstdcxx_printers (None) end
Eclipseでgdbinitの場所を指定.
Window -> preferences -> C/C++ -> Debug -> GDB参考
NDKを使うとどんくらい速くなるのか試す
とても実装が簡単なフィボナッチ数列の第N項を求めるだけの関数を使って,NDKを使った場合と使わなかった場合でどんくらい差が出るのか試した.
NDKを使う手順
- Androidプロジェクトの作成
- 右クリックして,AndroidTools->Add Native Support
- .javaファイルの方に,native指定子を付けてメソッドを宣言
- プロジェクトのビルド(これをしないと.classファイルがないと怒られる)
- jni以下にヘッダファイルを生成(javahを使う)
- 生成されたヘッダから宣言部分をコピペしてcppファイルに実装
fibonacci
Androidバイトコードの方はこっちprivate long fibo(int n) { if (n < 3) { return 1; } return fibo(n-1) + fibo(n-2); }
ネイティブコードの方はこっち
private native long fiboCpp(int n);//宣言 static { System.loadLibrary("fibo");//読み込み }
#include <jni.h> #include "fibo.hpp" long fibo( int n ) { if ( n < 3 ) { return 1; } return fibo(n-1) + fibo(n-2); } JNIEXPORT jlong JNICALL Java_com_example_hellondk_MainActivity_fiboCpp (JNIEnv *env, jobject obj, jint n) { return fibo( n ); }
ボタンを押したらスタートして,実行が終わったらTextViewに実行時間を表示するようにした.
実行結果
大体10倍くらいネイティブコードの方が速かった.考察
やっぱ機械語は速いんですねー.AsyncTaskを使って,onPreExecute()で開始時間を測り,onPostExecute()で終了時間を測った場合は,Nを小さくした場合でも10ms前後の時間がかかった
開始時間と終了時間の計測を,doInBaskground()内で行った場合は,Nが小さいとどちらの場合も0msになったので,メソッドを呼び出す分のロスだったのかなーと思われる.
また,Nの値にかかわらず実行時間の振れ幅がかなり大きいのも気になった.ガベージコレクションか,それとも他のプロセスが優先して実行されたのか.よくわからない.
実行結果に振れ幅が大きかったので,もっと大量にデータが欲しかったんだけど,ボタン押して画面で確認するのが辛いので諦めた.
_人人人人人人人人人人人人人人人人_
> GUIで操作しようとしたのが悪い <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
何回か試行してそのデータをグラフとして表示とかできるようにしたい…
コードはhttps://github.com/crakaC/NDK_sampleにおいているので煮るなり焼くなりしてください.