浅谈Android中用接口完美实现回调的逻辑控制

让Android融入我的生活!

公司最近项目特别忙,难得抽时间出来写博客了,不过越忙,接触的东西越多,学的也就越多了!

本例要特别强调一下:只是对高内聚,低耦合思想的一点简单实现,重要思想,而不是代码,请广大读者朋友留意!

前段时间公司Android开发就我一个人,思维太封闭了,自己想个啥样,就写个啥样,现在呢,来了两个同事,项目由我和另外一个同事一起负责,有人交流,可以听听别人的理解,对我们的提高绝对是有益无害,我们也需要调整好自己的心态,能够接受别人的正确建议!

好了,话不多说,进入正题,大家请先看一下下面这张图片,分为以下几个部分

1:进入页面对应的Activity,红标1为RadioButton,红标2为TextView,所有控制逻辑在当前Activity中实现

2:红色大方框,标注3的部分,是一个ImageSelectFragment,对应Activity中一个Framelayout布局,控制它显示和隐藏

3:ImageSelectFragment显示的所有图片,用一个GridView显示,给GridView配置上相应的GridAdapter

4:每张图片右上角有一个删除的按钮,在GridAdapter当中实现逻辑控制

那么现在问题来了,大家想想,我们写代码,尽量要实现它的高移植性,这也许就是Android高内聚,低耦合的思想精髓吧,让我们的代码直接拿给别人就能用,那这个ImageSelectFragment怎么样作到高内聚呢?

到这里,我们就需要搞清楚,这个ImageSelectFragment到底要实现什么,它内部都需要作些什么工作,对外传递些什么,理解清楚这些,我们才有高内聚的目标。

这个ImageSelectFragment所要实现的,就是所有图片选择的逻辑控制,不管你添加、删除、把图片Uri数据传给其它Activity、退出程序后再进来添加或者删除等等所有逻辑,这就是我们要实现的目标,当进行选择、删除时,红标为2的数字肯定也要变化,就是说,你的所有操作影响到数据变化时,一定要通知当前的Activity。

好了,大家看一下ImageSelectFragment的实现代码:

import java.io.File;

import java.io.Serializable;

import java.util.ArrayList;

import net.tsz.afinal.FinalBitmap;

import android.annotation.SuppressLint;

import android.content.Context;

import android.content.Intent;

import android.net.Uri;

import android.os.Bundle;

import android.os.Environment;

import android.provider.MediaStore;

import android.support.annotation.Nullable;

import android.util.Log;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.view.inputmethod.InputMethodManager;

import android.widget.AdapterView;

import android.widget.AdapterView.OnItemClickListener;

import android.widget.GridView;

import com.uhuibao.hupeng.BaseFragment;

import com.uhuibao.hupeng.R;

import com.uhuibao.hupeng.adapter.GridAdapter;

import com.uhuibao.hupeng.adapter.GridAdapter.DeleteImageListener;

import com.uhuibao.hupeng.config.Constants;

import com.uhuibao.hupeng.selectpic.BitmapUtils;

import com.uhuibao.hupeng.selectpic.ImageGridActivity;

import com.uhuibao.hupeng.selectpic.TestPicActivity;

import com.uhuibao.hupeng.utils.MToast;

/**

*

* @ClassName: ImageSelectFragment

* @Description: TODO 图片选择的逻辑控制

* @author AricMiao

* @date 2014-12-16 上午9:28:59

*/

@SuppressLint("InflateParams")

public class ImageSelectFragment extends BaseFragment {

public static final int PHOTOHRAPH = 1;// 拍照

public static final int PHOTOFROMLOCAL = 2; // 取照

public static final int PHOTOODELETE = 3;// 打开相册

public static final int PHOTOLOCAORESULT = 4;// 取照结果

public static final String IMAGE_UNSPECIFIED = "image/*";

/** 在tabhost的位置 */

public static final int POSITION = 0;

private View view;

public GridView gv_photo;

private GridAdapter adapter;// 放照片

private FinalBitmap friendsFb;

private Context mContext;

private ArrayList<String> urls=new ArrayList<String>();

private ImageSelectListener mListener;

@Override

public View onCreateView(LayoutInflater inflater,

@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

// TODO Auto-generated method stub

mContext=this.getActivity();

view = inflater.inflate(R.layout.image_select, null);

return view;

}

@Override

public void onActivityCreated(@Nullable Bundle savedInstanceState) {

// TODO Auto-generated method stub

super.onActivityCreated(savedInstanceState);

friendsFb = FinalBitmap.create(this.getActivity());

friendsFb.configDiskCachePath(Constants.picSavePath);

friendsFb.configLoadingImage(R.drawable.user);

friendsFb.configLoadfailImage(R.drawable.user);

// 照片容器

gv_photo = (GridView) view.findViewById(R.id.gv_photo);

adapter = new GridAdapter(this.getActivity(), friendsFb);

gv_photo.setAdapter(adapter);

adapter.notifyDataSetChanged();

gv_photo.setOnItemClickListener(new OnItemClickListener() {

public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,

long arg3) {

Log.d(Constants.TAG,

"===点击位置===" + arg2 + "===图片路劲list===" + urls.size());

if (arg2 == urls.size()) {

InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);

imm.hideSoftInputFromWindow(arg1.getWindowToken(), 0);

new PopupWindows(ImageSelectFragment.this.getActivity(), gv_photo,new ImageCallback() {

@Override

public void onSelectResult(String method) {

// TODO Auto-generated method stub

Intent intent=new Intent();

if("camera".equals(method)){

String state = Environment.getExternalStorageState();

if (state.equals(Environment.MEDIA_MOUNTED)) {

intent = new Intent(

MediaStore.ACTION_IMAGE_CAPTURE);

Constants.cameraFile = new File(Environment.getExternalStorageDirectory(),

String.valueOf(System.currentTimeMillis()) + ".jpg");

Log.d(Constants.TAG, "===相片保存路径===" + Constants.cameraFile.getPath());

Uri imageUri = Uri.fromFile(Constants.cameraFile);

intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, PHOTOHRAPH);

} else {

MToast.showToast(mContext, "木有SD卡哦");

}

}else if("local".equals(method)){

intent = new Intent(getActivity(),

TestPicActivity.class);

startActivityForResult(intent, PHOTOFROMLOCAL);

}else if("no".equals(method)){

}

}

});

}

}

});

adapter.setDeleteListener(deleteListener);

}

DeleteImageListener deleteListener=new DeleteImageListener() {

@Override

public void deleteImage(int position, String url) {

// TODO Auto-generated method stub

urls.remove(url);

if(mListener!=null){

mListener.imageSelct(urls);

}

}

};

public void onActivityResult(int requestCode, int resultCode, Intent data) {

switch (requestCode) {

case PHOTOFROMLOCAL:// 本地选取

if (resultCode == -1) {

return;

}

if (Constants.photoFiles != null) {

Intent intent = new Intent(getActivity(),

ImageGridActivity.class);

intent.putExtra(TestPicActivity.EXTRA_IMAGE_LIST,

(Serializable) Constants.photoFiles);

startActivityForResult(intent, PHOTOLOCAORESULT);

}

break;

case PHOTOHRAPH:// 拍照

Log.d(Constants.TAG, "===图片张数===" + BitmapUtils.drr.size()

+ "===结果码===" + resultCode + "===图片路径==="

+ Constants.cameraFile.getPath());

if (BitmapUtils.drr.size() < Constants.photoNum) {

if (Constants.cameraFile.exists()) {

BitmapUtils.drr.add(Constants.cameraFile.getPath());

}

}

break;

case PHOTOODELETE:

break;

case PHOTOLOCAORESULT:

break;

}

urls=BitmapUtils.drr;

if(mListener!=null){

mListener.imageSelct(urls);

}

super.onActivityResult(requestCode, resultCode, data);

}

@Override

public void onResume() {

// TODO Auto-generated method stub

adapter.notifyDataSetChanged();

super.onResume();

}

@Override

public void onDestroyView() {

// TODO Auto-generated method stub

view = null;

super.onDestroyView();

}

public interface ImageSelectListener{

public void imageSelct(ArrayList<String> urls);

}

public void setImageSelectListener(ImageSelectListener listener){

mListener=listener;

}

}

其实在当前ImageSelectFragment当中实现所有操作控制就不多说了,高内聚,低耦合的思想最主要的体现就在ImageSelectListener接口上:

public interface ImageSelectListener{

public void imageSelct(ArrayList<String> urls);

}

public void setImageSelectListener(ImageSelectListener listener){

mListener=listener;

}

我们可以在我们自己的Activity当中实现这个接口

ImageSelectListener mImageSelectListener=new ImageSelectListener() {

@Override

public void imageSelct(ArrayList<String> urls) {

// TODO Auto-generated method stub

mUrls=urls;

setImageTextNum();

}

};

当对图片数据进行操作时,任何导致数据变化的操作都让它回调到这个方法中,返回来的结果ArrayList<String> urls就是操作完成后,所有图片的路径了,只要能拿到这个路径,我们就可以任意设置Activity中的显示、传递逻辑了,而这样,我们根本不用关心用户对图片进行了什么操作、操作步骤是什么的、影响到什么这些经过,别人如果要移植我们的图片显示Fragment,也只需要在他自己的Activity中实现这个接口就可以了,非常方便,这样使我们的代码在一个完全封闭的环境中执行,只对外界公司一个开口就足够了,这种模式和很多朋友用的Callback回调机制基本上是相同的。

好了,就介绍到这里吧,如果有朋友愿意互相交流的话,可以加QQ:1531074759,谢谢!

时间: 2024-11-04 16:20:07

浅谈Android中用接口完美实现回调的逻辑控制的相关文章

安卓开发_浅谈Android动画(四)

Property动画 概念:属性动画,即通过改变对象属性的动画. 特点:属性动画真正改变了一个UI控件,包括其事件触发焦点的位置 一.重要的动画类及属性值: 1.  ValueAnimator 基本属性动画类 方法 描述 setDuration(long duration) 设置动画持续时间的方法 setEvaluator(TypeEvaluator value) 设置插值计算的类型 setInterpolator(TimeInterpolator value) 设置时间插值器的类型 addUp

浅谈Android应用保护(二):Anti-Analysis的方法和工具

本文内容翻译自国外文献,原文链接请参看文章底部 之前讲到过,应用开发者为了保护自己的应用不被别人分析和篡改,会将应用的安全性寄托在某个(些)机制上.可以被用来保护应用的机制有很多,效果和实现难度也是各有特点.有这样一类应用保护方法,叫做针对逆向工具的对抗(Anti-Analysis). 针对逆向工具的对抗,简单来讲就是利用逆向工具自身的缺陷或者是Android特有的机制,使应用逆向分析工具在工作过程中失效或者报错崩溃,分析过程无法继续实施.从而达到保护应用的目的. 这种保护应用的方式的优点就是实

浅谈Android多屏幕的事

浅谈Android多屏幕的事 一部手机可以同时看片.聊天,还可以腾出一支手来撸!这么吊的功能(非N版本,非第三方也能实现,你不知道吧)摆在你面前,你不享用?不关注它是怎样实现的?你来,我就满足你的欲望! 一部手机可以同时看片.聊天,还可以腾出一支手来撸==!就像这样: 是时候告别来回切换应用屏幕的酸爽了,还可以在分屏模式下两Activity间直接拖放数据! 好高大上的样子!这是怎么实现的?别急,我们一一道来: kitkat(4.4)版本对多任务分屏的实现 由于相关的代码和功能被封装及隐藏起来,所

浅谈 Android Service

 浅谈Android Service的基本用法: 关于Service最基本的用法自然是启动和停止操作. 启动Service有两种方式: 1.通过startService(Intent intent)方式启动,启动时会自动执行onCreate(),onStartCommand()方法. 2.通过bindService(Intent intent,ServiceConnection connection,int flag) 第一个参数是一个Intent对象,第二个参数是连接Service的实例,

浅谈Android五大布局

Android的界面是有布局和组件协同完成的,布局好比是建筑里的框架,而组件则相当于建筑里的砖瓦.组件按照布局的要求依次排列,就组成了用户所看见的界面.Android的五大布局分别是LinearLayout(线性布局).FrameLayout(单帧布局).RelativeLayout(相对布局).AbsoluteLayout(绝对布局)和TableLayout(表格布局). LinearLayout: LinearLayout按照垂直或者水平的顺序依次排列子元素,每一个子元素都位于前一个元素之后

浅谈Android五大布局(二)——RelativeLayout和TableLayout

在浅谈Android五大布局(一)中已经描述了LinearLayout(线性布局).FrameLayout(单帧布局)和AbsoulteLayout(绝对布局)三种布局结构,剩下的两种布局RelativeLayout(相对布局)和TableLayout(表格布局)相对之前布局结构稍显复杂一点,所以这里另起篇幅进行介绍. RelativeLayout: RelativeLayout按照各子元素之间的位置关系完成布局.在此布局中的子元素里与位置相关的属性将生效.例如android:layout_be

浅谈Android onClick与onLongClick事件触发的问题

之前做按钮的点击事件一直没有注意一些细节,今天做了一个按钮需要有点击和长点击触发不同效果,直接让Activity implements OnClickListener, OnLongClickListener然后添加了相应的处理函数. @Override public void onClick(View v) { // TODO Auto-generated method stub } @Override public boolean onLongClick(View v) { // TODO

浅谈Android保护技术__代码混淆

浅谈Android保护技术__代码混淆 代码混淆 代码混淆(Obfuscated code)亦称花指令,是将计算机程序的代码,转换成一种功能上等价,但是难于阅读和理解的形式的行为.将代码中的各种元素,如变量,函数,类的名字改写成无意义的名字.比如改写成单个字母,或是简短的无意义字母组合,甚至改写成"__"这样的符号,使得阅读的人无法根据名字猜测其用途.对于支持反射的语言,代码混淆有可能与反射发生冲突.代码混淆并不能真正阻止反向工程,只能增大其难度.因此,对于对安全性要求很高的场合,仅仅

浅谈Android五大布局(二)——RelativeLayout和TableLayout【转】

http://www.cnblogs.com/wisekingokok/archive/2011/08/24/2152004.html 在浅谈Android五大布局(一)中已经描述了LinearLayout(线性布局).FrameLayout(单帧布局)和AbsoulteLayout(绝对布局)三种布局结构,剩下的两种布局RelativeLayout(相对布局)和TableLayout(表格布局)相对之前布局结构稍显复杂一点,所以这里另起篇幅进行介绍. RelativeLayout: Relat