AQueryライブラリを使用したサンプルアプリケーション

プロジェクトでAQueryライブラリを使用する理由は常に 問われます。 結局、私たちは答えにうんざりしていたので、AQueryが戦闘で何ができるかを示すことにしました。



しかし、奇妙なhello world疑似コードを書くのは退屈で面白くないので、小さくても便利なアプリケーションを作成することにしました。 最近、MegamindプロジェクトはHabrから分離し、ニュースへのコメントで、すべてのリソースからのRSSフィードを結合する提案を表明しました。 これが私たちがやることです。



最終的に、次のITニュースアプリケーションのプロトタイプを取得します(Habr、Giktayms、megamindからのrss、siliconron / swarmで日付順にソート):



画像



速攻のリンク:

github: github.com/recoilme/itnews

google play: play.google.com/store/apps/details?id=org.freemp.itnews



最初に、ライブラリ自体について少し説明します。



ライブラリは主に以下を目的としています。

-UI要素の操作

-ネットワークでの作業

-画像を操作する



それは表面上だけです。



小さな外​​部依存関係なし。 使用を強制したり、他のライブラリと競合したりすることはなく、プログラミング時にスタイルを強制することもありません。 jarファイルをドロップするだけです。

だから、順番に:



UI要素の操作:書き込みを少なく、書き込みを高速化

AQueryを使用しないコード

public void renderContent(Content content, View view) { ImageView tbView = (ImageView) view.findViewById(R.id.icon); if(tbView != null){ tbView.setImageBitmap(R.drawable.icon); tbView.setVisibility(View.VISIBLE); tbView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { someMethod(v); } }); } TextView nameView = (TextView) view.findViewById(R.id.name); if(nameView != null){ nameView.setText(content.getPname()); } TextView timeView = (TextView) view.findViewById(R.id.time); if(timeView != null){ long now = System.currentTimeMillis(); timeView.setText(FormatUtility.relativeTime(now, content.getCreate())); timeView.setVisibility(View.VISIBLE); } TextView descView = (TextView) view.findViewById(R.id.desc); if(descView != null){ descView.setText(content.getDesc()); descView.setVisibility(View.VISIBLE); } }
      
      







AQueryを使用したコード

 public void renderContent(Content content, View view) { AQuery aq = new AQuery(view); aq.id(R.id.icon).image(R.drawable.icon).visible().clicked(this, "someMethod"); aq.id(R.id.name).text(content.getPname()); aq.id(R.id.time).text(FormatUtility.relativeTime(System.currentTimeMillis(), content.getCreate())).visible(); aq.id(R.id.desc).text(content.getDesc()).visible(); }
      
      







そして、そこにfindviewbyidを書くことを誰も禁止していません-好きなようにミックスしてください。 Javaではなく、GroovyまたはKotlinで記述しているように、コードはより簡潔で読みやすくなります。



ネットワークを操作します。 取得、投稿、マルチパートリクエスト。 アクティビティへの動的バインディング。 柔軟なすぐに使えるキャッシングシステム



非同期

(以降、エントロピーを生成しないように、wikiへのリンクを提供します)



画像をダウンロードします。 キャッシング、アニメーション、ダウンサンプリング、アスペクト比操作-メモリの問題を忘れてビジネスに取り掛かる



ImageLoading



Facebookからtwitterへのリソースの束による認証と同様に。 場所を操作します。 多数のデバッグユーティリティ、XML解析など



多数のサンプルを含む優れたドキュメント



しかし、これらはすべて言葉です。実際に試してみましょう。 次の依存関係を持つ空のプロジェクトを作成します。





AQuery広告から始めて、すべてが接続されていることを確認します。



 public class ActivityMain extends Activity { private AQuery aq; private Activity activity; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); activity = this; aq = new AQuery(activity); AQUtility.setDebug(true); } }
      
      







次に、カードを追加し、その仕組みを確認します。



 public class ActivityMain extends Activity { private AQuery aq; private Activity activity; private RecyclerView gridView; private StaggeredGridLayoutManager mLayoutManager; private AdapterMain adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activity = this; aq = new AQuery(activity); AQUtility.setDebug(true); gridView = new RecyclerView(activity); gridView.setHasFixedSize(true); mLayoutManager = new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL); gridView.setLayoutManager(mLayoutManager); gridView.setItemAnimator(new DefaultItemAnimator()); getWindow().setContentView(gridView); adapter = new AdapterMain(activity,new String[]{"123","456"}); gridView.setAdapter(adapter); } }
      
      







アダプター



 /** * Created by recoilme on 23/01/15. */ public class AdapterMain extends RecyclerView.Adapter<AdapterMain.ViewHolder> { private String[] data; private AQuery aq; private Activity activity; public AdapterMain(Activity activity,String[] data) { this.activity = activity; this.data = data; aq = new AQuery(activity); } public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public ViewHolder(View v) { super(v); mTextView = (TextView) v.findViewById(R.id.articleTitle); } } @Override public AdapterMain.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.card, parent, false); ViewHolder vh = new ViewHolder(v); return vh; } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { aq.id(viewHolder.mTextView).text(data[i]); } @Override public int getItemCount() { return data.length; } }
      
      







レイアウトカード:
 <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:id="@+id/card_view" android:layout_gravity="center" android:layout_width="match_parent" android:layout_height="wrap_content" card_view:contentPadding="8dp" card_view:cardBackgroundColor="@color/primary_bgr" card_view:cardUseCompatPadding="true" card_view:cardCornerRadius="4dp"> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/articleLayout" android:background="@color/primary_bgr" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:id="@+id/stgvImageView" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/stgvImageView" android:layout_alignRight="@+id/stgvImageView" android:gravity="center" android:layout_alignBottom="@+id/stgvImageView" android:layout_alignTop="@+id/stgvImageView" android:textColor="@color/white" android:textSize="20dp" android:id="@+id/siteurl" android:visibility="gone"/> <View android:layout_width="match_parent" android:layout_height="68dp" android:background="@drawable/main_adapter_tagbgr" android:layout_alignRight="@+id/stgvImageView" android:layout_alignTop="@+id/stgvImageView" android:layout_alignLeft="@+id/stgvImageView" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/stgvImageView" android:id="@+id/footer" android:orientation="vertical" android:paddingTop="16dp" android:paddingBottom="16dp" android:paddingLeft="6dp" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/articleTitle" android:textAppearance="@android:style/TextAppearance.Medium" android:textColor="@drawable/main_adapter_textselector" android:textStyle="bold" android:layout_marginBottom="16dp" android:paddingRight="8dp" android:paddingLeft="0dp"/> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:id="@+id/authorLayout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_alignParentStart="false" android:clickable="true" android:paddingTop="10dp" android:paddingBottom="10dp" android:baselineAligned="false" android:paddingRight="4dp" android:paddingLeft="0dp"> <ImageView android:id="@+id/userAva" android:layout_width="20dp" android:layout_height="20dp" android:layout_gravity="center_vertical" android:background="#f8f8f8" /> <TextView android:id="@+id/userFullname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:textColor="@color/gray_text" android:paddingLeft="8dp" android:ellipsize="end" android:maxWidth="160dp" android:singleLine="true" android:textAppearance="@android:style/TextAppearance.Small"/> </LinearLayout> </RelativeLayout> </LinearLayout> </RelativeLayout> </android.support.v7.widget.CardView>
      
      









何が起こったかを確認してください:




ここで、AQueryを使用してマジックを開始します。rssを取得して解析します。



aq.ajax(url、XmlDom.class、this、 "onRequest")を記述するだけです-AQueryが残りを行います



 public void request(String url) { aq.ajax(url, XmlDom.class,this,"onRequest"); } public void onRequest(String url,XmlDom xml, AjaxStatus status) { if (status.getCode()==200) { String logo = ""; try { logo = xml.tags("url").get(0).text(); } catch (Exception e) { e.printStackTrace(); } List<XmlDom> xmlItems = xml.tags("item"); for(XmlDom xmlItem: xmlItems){ ClassItem item = new ClassItem(); String description = xmlItem.tag("description").text(); item.setLogo(logo); item.setAuthor(xmlItem.tag("author").text()); item.setTitle(xmlItem.tag("title").text()); item.setDescription(description); item.setLink(xmlItem.tag("link").text()); String pubDate = xmlItem.tag("pubDate").text(); Date date = new Date(); try { date = formatter.parse(pubDate); } catch (Exception e) { AQUtility.debug("errorParsingDate",e.toString()); } item.setDate(date); String src = ""; try { src = new XmlDom("<xml>"+description+"</xml>").tag("img").attr("src"); if (src.startsWith("//") ) { src = "http:"+src; } } catch (Exception e) { e.printStackTrace(); } item.setImg(src); items.add(item); } adapter.notifyDataSetChanged(); } }
      
      





AjaxStatusクラスは、クエリ実行の結果に関する詳細情報を受け取ります+ AQueryには、単純なXMLパーサーが組み込まれています。 リクエストが完了した時点でアクティビティの可用性を心配する必要はありません。AQueryが自動的に処理します。 さらに、HTTP要求モジュールは上記の例よりもはるかに柔軟性があり、ヘッダーから要求実行メソッドまですべてをカスタマイズできます。 また、たとえば、リクエストをキャッシュする必要がある場合は、パラメータfileCache = trueとリクエストをキャッシュする時間を追加するだけです。 エラーなどの場合にキャッシュを無効にする機能があります。



アダプターに戻り、rssストリームを画像表示機能で強化します。 さらに、AQueryでは簡単ではありませんが、非常に簡単です。

 public class AdapterMain extends RecyclerView.Adapter<AdapterMain.ViewHolder> { private ArrayList<ClassItem> data; private AQuery aq; private Activity activity; private DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm", Locale.getDefault()); public AdapterMain(Activity activity,ArrayList<ClassItem> data) { this.activity = activity; this.data = data; aq = new AQuery(activity); } public static class ViewHolder extends RecyclerView.ViewHolder { private ImageView stgvImageView; private ImageView userAva; private TextView siteurl; private TextView userFullname; private TextView articleTitle; public ViewHolder(View holderView) { super(holderView); stgvImageView = (ImageView) holderView.findViewById(R.id.stgvImageView); siteurl = (TextView) holderView.findViewById(R.id.siteurl); userAva = (ImageView) holderView.findViewById(R.id.userAva); userFullname = (TextView) holderView.findViewById(R.id.userFullname); articleTitle = (TextView) holderView.findViewById(R.id.articleTitle); } } @Override public AdapterMain.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.card, parent, false); ViewHolder vh = new ViewHolder(v); return vh; } @Override public void onBindViewHolder(ViewHolder viewHolder, int i) { ClassItem item = data.get(i); aq.id(viewHolder.articleTitle).text(item.getTitle()); aq.id(viewHolder.siteurl).text(item.getLink()); aq.id(viewHolder.userAva).image(item.getLogo()); aq.id(viewHolder.userFullname).text(item.getAuthor() + " " + formatter.format(item.getDate())); if (TextUtils.equals(item.getImg(),"")) aq.id(viewHolder.stgvImageView).gone(); else { aq.id(viewHolder.stgvImageView).visible().image(item.getImg(), true, false, 640, 0, null, AQuery.FADE_IN, AQuery.RATIO_PRESERVE); } } @Override public int getItemCount() { return data.size(); } }
      
      







文字通り1行で、画像を縮小し、メモリへのキャッシュをオンにし、目的のアスペクト比までスキャンし、同時に表示アニメーションをオンにしました。



  aq.id(viewHolder.stgvImageView).visible().image(item.getImg(), true, false, 640, 0, null, AQuery.FADE_IN, AQuery.RATIO_PRESERVE);
      
      







ライブラリコードを見ると、画像を操作するロジック全体がweakReference上に構築されていること、LRUキャッシュが混雑に使用されていること、スケーリングが最適化されたinSampleSizeメソッドなどを使用して実行されていることがわかります。 さらに、さまざまなタイプの画像(小、大、中)のキャッシュサイズからキャッシュテクニック、キャッシュに保存される画像の数まで、キャッシュパラメータを手動で制御できます。



ファイルシステム(アプリケーションフラグメント)でキャッシュを無効にした構成の例



 @Override public void onLowMemory(){ //clear all memory cached images when system is in low memory //note that you can configure the max image cache count, see CONFIGURATION BitmapAjaxCallback.clearCache(); } @Override public void onCreate() { //Config cache BitmapAjaxCallback.setDelayWrite(true); BitmapAjaxCallback.setPixelLimit(640*800); BitmapAjaxCallback.setMaxPixelLimit(4096000); }
      
      







この場合、画像は一時ファイルにダウンロードされないため、一度に数百の画像をダウンロードする場合に便利です。



また、たとえば、ページをリロードするときのキャッシュの強制クリアは次のとおりです。



 BitmapAjaxCallback.clearCache();
      
      







実際、この例では、ページの更新を追加する必要があります。



  @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... swipeRefreshLayout = new SwipeRefreshLayout(activity); swipeRefreshLayout.setOnRefreshListener(this); swipeRefreshLayout.setColorScheme(android.R.color.holo_blue_bright, android.R.color.holo_green_light, android.R.color.holo_orange_light, android.R.color.holo_red_light); .... @Override public void onRefresh() { getFeeds(); }
      
      







それでは、フィードのリストを展開しましょう。



  private final String[] FEEDS = new String[]{"http://roem.ru/rss/","http://siliconrus.com/feed/","http://habrahabr.ru/rss/","http://megamozg.ru/rss/","http://geektimes.ru/rss/"};
      
      







その結果、主要なリソースのプールからrssフィードを読み取るためのアプリケーションが作成されました。AQueryのおかげで、ダンスをせずにライブラリを束ねて、実際にはプロセスではなくコードに集中して、わずか5時間で書き込みが可能になりました。 私たちがAQueryを愛しているのは&)



軟膏で飛ぶ-ライブラリはめったに更新されず、実際には開発されません。 一方では、その成熟度について語り、他方では、開発者はフレームワークの前に開発のための資金を集めたいと思っていたが、寄付モデルに失望し、得点した。 しかし、長年の使用を通じて、そのコードでエラーに遭遇したことは幸運ではありませんでした。他のライブラリに心から望んでいます。



PS:結果のrssリーダーをgithubに投稿しました。 もちろん、これは単なるプロトタイプですが、非常に機能しています:

github.com/recoilme/itnews

google play: play.google.com/store/apps/details?id=org.freemp.itnews



All Articles