Androidã®ãã¶ã¤ã³ãã¿ã¼ã³ãèãã¦ã¿ã
ä¸çªææ°ã®ãã¤ã¯ãã£ã¡
åæ
æ°ãããã©ã¤ã¨ãã¦Androidãæ¸ãå§ãã¦ã ãããåå¹´ããããã£ãã®ã§ãããæç§æ¸éãã«ã³ã¼ããæ¸ãã¦ãããã®ã®APIãå¼ã¶ãããã®å®è£ ãã©ãã«ããã£ããããªããã£ãã®ã§ãè¯ãæ©ä¼ã ã¨æãè¨è¨ãè¦ç´ãäºã«ãã¾ããã 以ä¸ããã£ã¡ãåèã«ããã¹ã©ã¤ãããããããã
iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い
ãã¤ã³ã
- åºæ¬çã«Modelã¯æ»ãªãªã + éç¥ã§å¤æ´ãä¼ããå½¹å²ãæã¤
- ViewãVCã§APIãå¼ã¶ã®ã¯ã¦ã¼ã¶ã¼ã®æä½ã«å½±é¿ãããããããããã
ä½ã£ã¦ã¿ã
以åããã®ãã¹ãã§Atndã®APIãå¼ãã§çµæãListViewã«è¡¨ç¤ºãã¦ã¿ãã¨ããã®ãåå¼·ã®ã¢ã¦ããããã¨ãã¦æ®ããã®ã§ãããä»åã¯ãããä¸è¨ã®ãã¤ã³ããè¸ã¾ããä¸ã§Observerãã¿ã¼ã³ã§æ¸ãç´ãã¦ã¿ããã¨æãã¾ãã
ãã£ã¨æ¦è¦
- ModelLocatorã»ã»ã»ä¸ã®ã¹ã©ã¤ãã«ãªããåãååã«ãã¦ã¿ããã·ã³ã°ã«ãã³ã§ã¢ããªã®èµ·åæã«Modelã®ã¤ã³ã¹ã¿ã³ã¹ãæ ¼ç´ãã¦ä¿æãã¦ãã
- Fragment ã»ã»ã» 観å¯è ãObserverãå®è£ ãã¦Modelããã®éç¥ããã£ãããã
- Modelã»ã»ã»Atndã®Apiã管çãããObservableã¨LoaderCallbacksãå®è£ ãã¦ãAPIã®å¼ã³åºããã¨ãã¤ãã³ããObserverã«éç¥ãã¨ããå½¹å²ãæ ã
- Entityã»ã»ã»Atndã®Eventæ å ±Entityãä»åã¯IDã¨ã¿ã¤ãã«ã ãæã¤ãã¦ãã¨ã¼
ã³ã¼ã
- ModelLocator
package me.rei_m.androidsample.model; /** * Created by rei_m on 2015/01/25. */ public class ModelLocator { private final static ModelLocator instance = new ModelLocator(); public static ModelLocator getInstance() {return instance;} private ModelLocator() {} private AtndApi atndApi; public AtndApi getAtndApi() { return atndApi; } public void setAtndApi(AtndApi atndApi) { this.atndApi = atndApi; } }
ã¢ããªèµ·åæã«AtndApiã®ã¢ãã«ãã»ãããã¦ãã
// ã¢ãã«ã®åæå ModelLocator.getInstance().setAtndApi(AtndApi.createInstance());
- AtndApi
package me.rei_m.androidsample.model; import android.app.LoaderManager; import android.content.Context; import android.content.Loader; import android.os.Bundle; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; import java.util.Observable; import me.rei_m.androidsample.entity.AtndEvent; import me.rei_m.androidsample.util.HttpAsyncLoader; /** * Atnd APIã管çããã¢ãã«. * APIã«ãªã¯ã¨ã¹ããé£ã°ããåå¾ããçµæããªã¹ãã§ä¿æãã¦ãåå¾å®äºã®ã¤ãã³ããéç¥ãã * * Created by rei_m on 2015/01/25. */ public class AtndApi extends Observable implements LoaderManager.LoaderCallbacks<String>{ public static AtndApi createInstance(){ return new AtndApi(); } private final int LOADER_ID = 1; private AtndApi(){} private Context mContext; private Loader mLoader; private List<AtndEvent> mList; public List<AtndEvent> getList(){ return mList; } /** * Loaderã®åæåãè¡ããAPIã¸ãªã¯ã¨ã¹ããé£ã°ã * * @param context Context * @param lm LoaderManager */ public void fetchList(Context context, LoaderManager lm){ mList = new ArrayList<>(); mContext = context; mLoader = lm.initLoader(LOADER_ID, null, this); mLoader.forceLoad(); } @Override public Loader<String> onCreateLoader(int id, Bundle args) { HttpAsyncLoader loader = new HttpAsyncLoader(mContext, "https://api.atnd.org/events/?keyword_or=google,cloud&format=json"); loader.forceLoad(); return loader; } @Override public void onLoadFinished(Loader<String> loader, String data) { if(loader.getId() == LOADER_ID){ try { // APIã®åå¾çµæãEventãªãã¸ã§ã¯ãã«å¤æãã¦æ ¼ç´ãã JSONObject json = new JSONObject(data); int evCnt = json.getInt("results_returned"); if(evCnt > 0){ JSONArray events = json.getJSONArray("events"); for(int i=0;i<evCnt;i++){ JSONObject ev = events.getJSONObject(i).getJSONObject("event"); AtndEvent atndEvent = new AtndEvent(); atndEvent.setId(ev.getString("event_id")); atndEvent.setTitle(ev.getString("title")); mList.add(atndEvent); } } } catch (JSONException e) { e.printStackTrace(); } } // Observerã«æ´æ°ãéç¥ãã LoaderEvent event = new LoaderEvent(this); setChanged(); notifyObservers(event); } @Override public void onLoaderReset(Loader<String> loader) { } }
- AtndEvent
package me.rei_m.androidsample.entity; import java.io.Serializable; /** * Created by rei_m on 2015/01/25. */ public class AtndEvent implements Serializable { private String id; private String title; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { return title; } }
- Fragment
package me.rei_m.androidsample.fragment; import android.app.Activity; import android.os.Bundle; import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AdapterView; import android.widget.ArrayAdapter; import java.util.Observable; import java.util.Observer; import me.rei_m.androidsample.R; import me.rei_m.androidsample.entity.AtndEvent; import me.rei_m.androidsample.model.AtndApi; import me.rei_m.androidsample.model.LoaderEvent; import me.rei_m.androidsample.model.ModelLocator; public class ObserverSampleFragment extends Fragment implements AbsListView.OnItemClickListener, Observer{ private OnFragmentInteractionListener mListener; private ArrayAdapter<AtndEvent> mAdapter; /** * AtndAPIã¢ãã« */ private AtndApi mAtndApi; /** * ãã¡ã¯ããªã¡ã½ãã * * @return ã¤ã³ã¹ã¿ã³ã¹ */ public static ObserverSampleFragment newInstance() { ObserverSampleFragment fragment = new ObserverSampleFragment(); Bundle args = new Bundle(); fragment.setArguments(args); return fragment; } /** * Mandatory empty constructor for the fragment manager to instantiate the * fragment (e.g. upon screen orientation changes). */ public ObserverSampleFragment() { } @Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1); // ModelLocatorããAtndAPIã¢ãã«ãåå¾ãã¦ãã©ã°ã¡ã³ããObserverã¨ãã¦ç»é²ãã mAtndApi = ModelLocator.getInstance().getAtndApi(); mAtndApi.addObserver(this); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_item, container, false); AbsListView listView = (AbsListView) view.findViewById(android.R.id.list); listView.setAdapter(mAdapter); listView.setOnItemClickListener(this); // AtndAPIã¢ãã«ããåå¾çµæãåãåºããå¤ãåå¨ããªãå ´åã¯ãªã¯ã¨ã¹ããæãã // å®éã«ã¯APIã®ãªã¯ã¨ã¹ããã©ã¡ã¼ã¿ã¨ãã¯å¤ããã¯ããªã®ã§ãå®ç¨ãèãããããã¡ããå³å¯ãªå¤å®ã«ãªãã¯ãã ãã©ã if(mAtndApi.getList() == null){ mAtndApi.fetchList(view.getContext(), getLoaderManager()); }else{ mAdapter.addAll(mAtndApi.getList()); mAdapter.notifyDataSetChanged(); } return view; } @Override public void onDestroy() { super.onDestroy(); // AtndAPIã¢ãã«ãããã©ã°ã¡ã³ããObserverããåé¤ãã mAtndApi.deleteObserver(this); } @Override public void onDetach() { super.onDetach(); mListener = null; mAtndApi = null; } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (null != mListener) { // Notify the active callbacks interface (the activity, if the // fragment is attached to one) that an item has been selected. mListener.onFragmentInteraction(position); } } @Override public void update(Observable observable, Object data) { if (data instanceof LoaderEvent){ // AtndAPIã¢ãã«ããéç¥ãåãåã£ããã¢ãã«ããAPIã®åå¾çµæãåãåºãã¦ãListViewã«ã»ãããã¦ãViewãæ´æ° AtndApi atndApi = (AtndApi) ((LoaderEvent) data).getSource(); mAdapter.addAll(atndApi.getList()); mAdapter.notifyDataSetChanged(); } } /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p/> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ public interface OnFragmentInteractionListener { // TODO: Update argument type and name public void onFragmentInteraction(int id); } }
ã ããããããªæãã§ããããã¼ã
å®è¡ãã¦ã¿ã
ãã¡ããå©ãã¦ã¾ãï¼https://api.atnd.org/events/?keyword_or=google,cloud&format=jsonï¼
ã§ããã¼ãã³ã¼ãã¯GitHubã«ä¸ãã£ã¦ã¾ã(https://github.com/rei-m/androidSample) æ®æ®µã¯Javaå°éã¦è¨³ã§ããªãã®ã§ããããªã¨ãããããã°æãã¦ä¸ããï¼