Android 创建模块化接口

原创 2015年07月10日 23:19:54

开发过程中通常会碰到这些问题:Activity越来越臃肿,界面中会有越来越多的业务代码,请求代码,上层的耦合越来越严重,维护起来会相当麻烦。项目开发时如果能有一个好的结构是至关重要的,比如最近的MVP架构主要就可以把Activity中的业务代码抽取出来,使Activity层的代码充分解耦,但是实现起来也需要耗费大量精力。这里介绍一种简单的方法来抽取Activity层的业务代码,就是利用Fragment来创建可以复用的模块。

为什么用Fragment

Fragment拥有和Activity很相似的生命周期,onCreate() , onDestroy() 还有自己的生命周期 onAttach() ,onCreateView 。Fragment本身如果不去重写onCreateView()的话是不会有界面的,从而可以把它当做一个纯粹的数据源,或者一个接口模块来进行复用,同时我们还可以利用FragmentManager来很方便的进行通信。

示例

作为dota爱好者这里简单写一个英雄选择的模块
先来实现数据模块 DataFragment,说道英雄选择肯定要有文字和图片

public class DataFragment extends Fragment {

    public static final String TAG = "data";


    public class DataItem{
        private String title;
        private int resId;

        public DataItem(String title, int resId) {
            this.title = title;
            this.resId = resId;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public int getResId() {
            return resId;
        }

        public void setResId(int resId) {
            this.resId = resId;
        }
    }

    public static DataFragment newInstance() {
        DataFragment fragment = new DataFragment();
        return fragment;
    }

    public DataFragment() {
        // Required empty public constructor
    }

    private ArrayList<DataItem> dataList;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dataList = new ArrayList<>();
        dataList.add(new DataItem("敌法师",R.mipmap.df));
        dataList.add(new DataItem("冰蛙亲儿子",R.mipmap.fw));
        dataList.add(new DataItem("和谐脸",R.mipmap.hexielian));
    }

    public List<DataItem> getData(){
        return dataList;
    }

DataFragment 声明了一个Dataitem内部类用来保存文字,和图片资源id,并在onCreate()中进行赋值,最后提供了一个获取数据的方法。很好理解

选择英雄列表

选择英雄列表选择用一个 DialogFragment来做,原因纯粹是拿来熟悉一下

public class ChooseFragment extends DialogFragment implements AdapterView.OnItemClickListener{

    //回调接口
    private ItemClick mListener;
    private ArrayAdapter mAdapter;

    //工厂方法给出ChooseFragment的实例
    public static ChooseFragment newInstance() {
        ChooseFragment fragment = new ChooseFragment();
        return fragment;
    }

    public ChooseFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //使用最简单的ArrayAdapter来实现列表
        mAdapter = new ArrayAdapter<DataFragment.DataItem>(getActivity(),android.R.layout.simple_list_item_1){
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                if(convertView == null){
                    convertView = LayoutInflater.from(getActivity()).inflate(android.R.layout.simple_list_item_1,parent,false);
                }
        //列表的TextView进行赋值
                DataFragment.DataItem item = getItem(position);
                TextView text = (TextView)convertView.findViewById(android.R.id.text1);
                text.setText(item.getTitle());
                return convertView;
            }
        };
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        ListView list = new ListView(getActivity());
        list.setAdapter(mAdapter);
        list.setOnItemClickListener(this);
        return list;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        Dialog dialog = super.onCreateDialog(savedInstanceState);
        //设置了一个选择框的标题
        dialog.setTitle("请选择你的英雄");
        return dialog;
    }

    @Override
    public void onResume() {
        super.onResume();
        //获得最新的数据
        DataFragment df = (DataFragment)getFragmentManager().findFragmentByTag(DataFragment.TAG);
        if(df != null){
            //更新选择数据
            mAdapter.clear();
            for (DataFragment.DataItem item : df.getData()) {
                mAdapter.add(item);
            }
            mAdapter.notifyDataSetChanged();
        }

    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //将onItemClick事件 回调出去
            mListener.ItemClick((DataFragment.DataItem) mAdapter.getItem(position));
            //如果显示对话框将对话框消失
            if(getShowsDialog()){
                dismiss();
            }
    }

    /**
     *onAttach中连接监听接口 确保Activity支持该接口
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (ItemClick) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    /**
     * onDetach中注销接口
     */
    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    //fragment内部自己声明的回调接口
    public interface ItemClick {
        // TODO: Update argument type and name
        public void ItemClick(DataFragment.DataItem item);
    }

ChooseFragment继承DialogFragment 整个界面是一个文字列表,文本用DataItem中的title来进行赋值,使用回调的方式将 listview 的OnItemClickListener事件回调出去。需要注意一点有用的细节就是这里展示了一种Fragment之间通信的方法,onResume()中通过TAG来关联DataFragment,然后通过直接调用DataFragment中的 getData() 方法来获取数据

英雄展示

选择完成后就是展示界面,用一个图片来展示就可以了

public class DetailFragment extends Fragment {

    private ImageView imageView;


    public DetailFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        imageView = new ImageView(getActivity());
        return imageView;
    }

    //画图
    public void paint(int resId){
        imageView.setImageResource(resId);
    }

非常简单,不多说明了。现在数据模块,列表模块,显示模块,都已经写好。剩下的工作就是把3者整合到一起。

Activity中整合

先来看Activity的布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:onClick="onShowClick"
        android:text="进入英雄选择"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></Button>

    <fragment
        android:id="@+id/fragment_detail"
        android:name="com.haibuzou.common.DetailFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

button按钮用来调出ChooseFragment 选择列表,已经设置好了点击事件,DetailFragment 用来显示英雄图片。

public class MainActivity extends AppCompatActivity implements ChooseFragment.ItemClick{

    private DetailFragment mDetail;
    private ChooseFragment mChoose;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DataFragment df = (DataFragment)getSupportFragmentManager().findFragmentByTag(DataFragment.TAG);
        if(df == null){
            df = DataFragment.newInstance();
            //希望保存这个实例,在配置变化时 比如横竖屏时获得同一个实例
            df.setRetainInstance(true);
            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            //通过Tag而不是id来关联fragment
            ft.add(df,DataFragment.TAG);
            ft.commit();
        }
        //通过xml中的id 获得详情fragment
        mDetail = (DetailFragment)getSupportFragmentManager().findFragmentById(R.id.fragment_detail);
        //获取选择框的Fragment实例
        mChoose = ChooseFragment.newInstance();

    }

    public void onShowClick(View v){
        mChoose.show(getSupportFragmentManager(),null);
    }

    @Override
    public void ItemClick(DataFragment.DataItem item) {
        mDetail.paint(item.getResId());
    }
}

Activity中首先去关联DataFragment,这里有一个小细节setRetainInstance(true) 这个设置是为了告诉FragmentManager即使Ui发生变化比如:横竖屏,也要保存这个DataFragment,保证至始至终只有一个数据模型。接着通过xml中的id R.id.fragment_detail 关联DetailFragment,最后用代码去创建列表 ChooseFragment,并且实现了ChooseFragment中的回调,执行ListView的点击操作。
就这样Fragment把代码整个模块化了。

  1. DataFragment数据模块 只负责提供数据
  2. ChooseFragment 列表模块 只负责显示列表数据
  3. Activity 作为最高指挥官负责整个界面的点击事件,跳转逻辑

3者各司其职,Activity也不再臃肿,并且这些模块都可以进行复用。是不是跃跃欲试了呢

这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/DanteStones/article/details/46836177

Android接口与未来性设计

-
  • 1970年01月01日 08:00

Android组件化之模块解耦和通信

针对Android组件化,组件间解耦和通信而创建的一个轻量级的框架
  • u010014658
  • u010014658
  • 2016-12-22 20:07:26
  • 5867

得到App Android组件化方案解析

为什么要写这篇文章 组件化已经深得客户端开发大神们的认可,组件化确实进一步优化了客户端团队的开发效率,更适合大团队分组推进,理解组件化的思想,深入研究组件化的实现方案是很必要的。 在接触众多组件化...
  • coder_nice
  • coder_nice
  • 2018-01-06 14:40:34
  • 658

Android项目模块化介绍——用注解使各个模块间不再依赖

Android项目一般都是一个project,用到的独立的库的就是一个library,library用第三方...
  • mzm489321926
  • mzm489321926
  • 2015-09-14 10:37:29
  • 2814

Android与蓝牙串口模块通信

由于项目的需要Android与蓝牙模块通信,发了时间学习了下,实现了Android与蓝牙模块的通信 1.蓝牙串口模块使用SPP-CA模块 蓝牙串口模块就是使用单片机的TX ,RX与蓝牙模块通信,单片机...
  • cwcwj3069
  • cwcwj3069
  • 2015-05-14 17:37:05
  • 38859

Android 开发:由模块化到组件化(一)

当你看到这的时候,想必心理一阵恶寒:模块化?组件化?到底是什么鬼?有啥区别. 有这种感觉才是对的,模块化和组件化本质思想是一样的,都是"大化小",两者的目的都是为了重用和解耦,只是叫法不一样.如果非要...
  • dd864140130
  • dd864140130
  • 2016-12-15 01:43:15
  • 33972

Android源码中增加模块

Android build system就是编译系统的意思  在我们需要向自己编译的源代码中增加模块的时候,需要一些规则,当然这个规则都是类似的。  Android.mk文件解析  ...
  • huiguixian
  • huiguixian
  • 2013-08-07 11:16:22
  • 4651

Android彻底组件化demo发布

今年6月份开始,我开始负责对“得到app”的android代码进行组件化拆分,在动手之前我查阅了很多组件化或者模块化的文章,虽然有一些收获,但是很少有文章能够给出一个整体且有效的方案,大部分文章都只停...
  • baidu_29153685
  • baidu_29153685
  • 2017-09-08 20:06:34
  • 1409

越是无理客户需求越应该重视,云服务产品化的构想

Scrum SaaS 补丁包/安装包 持续集成()
  • chagaostu
  • chagaostu
  • 2014-05-23 10:34:25
  • 573

Android的面向组件开发

面向组件思想是在软件规模扩大,复杂度上升的背景下,以面向对象为基础而提出的一种软件设计思想。可以把它理解为一种更粗粒度的面向对象,其粒度一般大于对象,但具体要到什么程度,又可以根据实际情况来决定。这种...
  • YANGWEIQIAO
  • YANGWEIQIAO
  • 2016-10-05 02:34:22
  • 161
收藏助手
不良信息举报
您举报文章:Android 创建模块化接口
举报原因:
原因补充:

(最多只允许输入30个字)