MVP


依赖
useLibrary 'org.apache.http.legacy'

//Volley依赖
implementation 'com.android.volley:volley:1.1.1-rc1'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.github.ikidou:TypeBuilder:1.0'
/**
 * 日志打印库
 */
implementation 'com.orhanobut:logger:2.2.0'
//图片加载库
implementation 'com.github.bumptech.glide:glide:3.8.0'
//大图浏览库
implementation 'com.ycjiang:ImagePreview:2.1.7'
//九宫格图片展示
implementation 'com.jaeger.ninegridimageview:library:1.1.1'
//图片加载库
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'

ICallBack 接口

public interface ICallBack {
     void success(List<Comment> data);
     void failed(String msg);
}
 
ICommentTask 接口
 

 
public interface ICommentTask {
    void getCommentList(String url,ICallBack callBack);
}
CommentContract 接口

public interface CommentContract {

    public interface ICommentPresenter extends BasePresenter {
        void getCommentList();
    }

    public interface ICommentView extends BaseView<CommentPresenter> {
        /**
         * 展示数据
         * @param list
         */
        void showData(List<Comment> list);

        void showError(String string);
    }

}
CommentTask 

public class CommentTask implements ICommentTask {
    @Override
    public void getCommentList(String url, final ICallBack callBack) {
        RequestQueue queue = Volley.newRequestQueue(App.context);
        StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Logger.json(response);
                RootData<Comment> data = fromJsonArray(response, Comment.class);
                callBack.success(data.data);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                callBack.failed(error.getMessage());
            }
        });

        queue.add(request);

    }

    /**
     * 解析泛型类
     * @param reader
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> RootData<T> fromJsonArray(String reader, Class<T> clazz) {
        Type type = TypeBuilder
                .newInstance(RootData.class)
                .addTypeParam(clazz)
                .build();
        return new Gson().fromJson(reader, type);
    }


}
 
CommentPresenter 

public class CommentPresenter implements ICommentPresenter {


    CommentTask task;

    ICommentView view;

    /**
     * 构造方法
     *
     * @param activity
     */
    public CommentPresenter(CommentActivity activity) {
        task = new CommentTask();
        view = activity;
    }


    /**
     * 首次加载
     */
    public void getFirstData(){
        getCommentList(0,10,false);
    }

    /**
     * 加载更多数据
     * @param page
     */
    public void getMoreData(int page){
        getCommentList(1,10,false);
    }

    /**
     * 刷新数据
     */
    public void refreshData(){
        getCommentList(0,10,true);
    }


    /**
     * 获取列表
     *
     * @param page
     * @param count
     */
    @Override
    public void getCommentList(final int page, int count, final boolean isRefresh) {

        String url = "http://39.108.3.12:3000/v1/comment?restaurant_id=32&offset=" + page + "&limit=" + count;

        task.getCommentList(url, new ICallBack() {
            @Override
            public void success(List<Comment> data) {
                if (view != null) {
                    if (page == 0) {
                        if (isRefresh) {
                            view.showRefreshData(data);
                        } else {
                            view.showFirstData(data);
                        }
                    } else {
                        view.showMoreData(data);
                    }
                }
            }

            @Override
            public void failed(String msg) {
                if (view != null)
                    view.showError(msg);
            }
        });
    }


    @Override
    public void start() {

    }

    /**
     * 销毁,防止内存泄漏
     */
    @Override
    public void onDestroy() {
        view = null;
    }
}
ICommentPresenter 

public interface ICommentPresenter extends BasePresenter {
    void getCommentList(int page,int count,boolean isRefresh);
}
 
CommentActivity 

 
public class CommentActivity extends AppCompatActivity implements ICommentView {

    CommentPresenter presenter;
    ListView listView;

    CommentAdapter adapter=new CommentAdapter(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.lv_comment);
        setPresenter(new CommentPresenter(this));

        presenter.getFirstData();//首次加载

        /**
         * 在XListView中的加载更多监听中调用
         */
        presenter.getMoreData(1);//加载更多

        /**
         * 在XListView中的刷新监听中调用
         */
        presenter.refreshData();//刷新数据
    }

    /**
     * 首次加载
     * @param list
     */
    @Override
    public void showFirstData(List<Comment> list) {
        //TODO 处理列表
        Logger.d(list);
        adapter.addDatas(list);
        listView.setAdapter(adapter);
    }

    /**
     * 加载更过
     * @param list
     */
    @Override
    public void showMoreData(List<Comment> list) {
        adapter.addDatas(list);
        listView.setAdapter(adapter);
    }

    /**
     * 下拉刷新
     * @param list
     */
    @Override
    public void showRefreshData(List<Comment> list) {
        adapter.clearData();//清除原有数据
        //添加数据
        adapter.addDatas(list);
        listView.setAdapter(adapter);
    }

    /**
     * 注入P
     *
     * @param presenter
     */
    @Override
    public void setPresenter(CommentPresenter presenter) {
        this.presenter = presenter;
    }

    /**
     * 网络请求错误的时候执行
     *
     * @param string
     */
    @Override
    public void showError(String string) {
        //TODO 弹出错误信息
    }


}
ICommentView 

public interface ICommentView extends BaseView<CommentPresenter> {
    /**
     * 展示数据
     * @param list
     */
    void showFirstData(List<Comment> list);
    void showMoreData(List<Comment> list);
    void showRefreshData(List<Comment> list);
    void showError(String string);


}

适配器

public class CommentAdapter extends BaseAdapter {

    public static final int TYPE_TEXT = 0;
    public static final int TYPE_TEXT_IMAGE = 1;
    public static final int TYPE_COUNT = 2;

    private List<Comment> comments;
    private Context context;

    private LayoutInflater inflater;
    private ImageLoader loader;
    DisplayImageOptions optionsCircle;
    DisplayImageOptions options;

    public CommentAdapter(Context context) {
        this.comments = new ArrayList<>();
        this.context = context;
        rthis.inflater = LayoutInflater.from(context);
        loader = ImageLoader.getInstance();
        optionsCircle = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher_round) // resource or drawable
                .showImageForEmptyUri(R.mipmap.ic_launcher_round) // resource or drawable
                .showImageOnFail(R.mipmap.ic_launcher_round) // resource or drawable
                .cacheInMemory(true) // default
                .cacheOnDisk(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
                .bitmapConfig(Bitmap.Config.RGB_565) // default
                .displayer(new CircleBitmapDisplayer(Color.BLACK, 1)) // default
                .build();

        options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher_round) // resource or drawable
                .showImageForEmptyUri(R.mipmap.ic_launcher_round) // resource or drawable
                .showImageOnFail(R.mipmap.ic_launcher_round) // resource or drawable
                .cacheInMemory(true) // default
                .cacheOnDisk(true) // default
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default
                .bitmapConfig(Bitmap.Config.RGB_565) // default
                .displayer(new SimpleBitmapDisplayer()) // default
                .build();
    }

    /**
     * 添加数据
     *
     * @param list
     */
    public void addDatas(List<Comment> list) {
        this.comments.addAll(list);
        notifyDataSetChanged();
    }

    /**
     * 清除数据
     */
    public void clearData(){
        this.comments.clear();
    }

    @Override
    public int getCount() {
        return comments.size();
    }

    @Override
    public Comment getItem(int i) {
        return comments.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public int getItemViewType(int position) {
        Comment comment = getItem(position);
        if (comment.pic_url != null && !comment.pic_url.isEmpty()) {
            return TYPE_TEXT_IMAGE;
        } else {
            return TYPE_TEXT;
        }
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_COUNT;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolderText holderText = null;
        ViewHolderTextImage holderTextImage = null;

        int type = getItemViewType(i);
        final Comment comment = getItem(i);

        if (view == null) {
            if (type == TYPE_TEXT) {
                view = inflater.inflate(R.layout.item_text, viewGroup, false);
                holderText = new ViewHolderText(view);
                view.setTag(holderText);
            } else if (type == TYPE_TEXT_IMAGE) {
                view = inflater.inflate(R.layout.item_text_image, viewGroup, false);
                holderTextImage = new ViewHolderTextImage(view);
                view.setTag(holderTextImage);
            }
        } else {
            if (type == TYPE_TEXT) {
                holderText = (ViewHolderText) view.getTag();
            } else if (type == TYPE_TEXT_IMAGE) {
                holderTextImage = (ViewHolderTextImage) view.getTag();
            }
        }


        if (type == TYPE_TEXT) {
            holderText.user_name.setText(comment.user_name);
            holderText.user_comment.setText(comment.comment_data);
            holderText.user_comment_time.setText(comment.comment_time);
            loader.displayImage(comment.avatar, holderText.user_icon, optionsCircle);
        } else if (type == TYPE_TEXT_IMAGE) {
            holderTextImage.user_name.setText(comment.user_name);
            holderTextImage.user_comment.setText(comment.comment_data);
            holderTextImage.user_comment_time.setText(comment.comment_time);


            final NineGridImageView nineGridImageView=holderTextImage.user_images;
            NineGridImageViewAdapter<String> adapter = new NineGridImageViewAdapter<String>() {
                @Override
                protected void onDisplayImage(Context context, ImageView imageView, String s) {
                    loader.displayImage(s, imageView, options);
                }

                @Override
                protected void onItemImageClick(Context context, ImageView imageView, int index, List<String> list) {
                    super.onItemImageClick(context, imageView, index, list);

                    List<PhotoInfo> infos = new ArrayList<>();
                    for (String url : comment.pic_url) {
                        infos.add(new PhotoInfo(url));
                    }

                    /**
                     * 拼接集合
                     */
                    computeBoundsBackward(nineGridImageView,infos);

                    /**
                     * 跳转
                     */
                    GPreviewBuilder.from((Activity) context)
                            .setData(infos)
                            .setCurrentIndex(index)//
                            .setType(GPreviewBuilder.IndicatorType.Number)
                            .start();//启动
                }
            };

            holderTextImage.user_images.setAdapter(adapter);
            holderTextImage.user_images.setImagesData(comment.pic_url);
        }

        return view;
    }

    /**
     * 只是文字
     */
    static class ViewHolderText {
        TextView user_name;
        TextView user_comment;
        TextView user_comment_time;
        ImageView user_icon;

        public ViewHolderText(View view) {
            user_name = (TextView) view.findViewById(R.id.user_name);
            user_comment = (TextView) view.findViewById(R.id.user_comment);
            user_comment_time = (TextView) view.findViewById(R.id.user_comment_time);
            user_icon = (ImageView) view.findViewById(R.id.user_icon);
        }
    }

    /**
     * 图片加文字
     */
    static class ViewHolderTextImage extends ViewHolderText {
        NineGridImageView user_images;

        public ViewHolderTextImage(View view) {
            super(view);
            this.user_images = (NineGridImageView) view.findViewById(R.id.user_images);
        }
    }

    /**
     * 查找信息
     * @param user_images 九宫格控件
     * @param list 数据列表
     */
    private void computeBoundsBackward(NineGridImageView user_images, List<PhotoInfo> list) {
        for (int i = 0; i < user_images.getChildCount(); i++) {
            View itemView = user_images.getChildAt(i);//
            Rect bounds = new Rect();
            if (itemView != null) {
                ImageView thumbView = (ImageView) itemView;
                thumbView.getGlobalVisibleRect(bounds);
            }
            list.get(i).mBounds = bounds;
        }

    }
}
PhotoInfo 

public class PhotoInfo implements IThumbViewInfo {
    public String url;  //图片地址(必须)
    public Rect mBounds; // 记录坐标(必须)
    public String user = "用户字段";//可选
    public String videoUrl;//必须

    public PhotoInfo(String url) {
        this.url = url;
    }

    protected PhotoInfo(Parcel in) {
        this.url = in.readString();
        this.mBounds = in.readParcelable(Rect.class.getClassLoader());
        this.user = in.readString();
        this.videoUrl = in.readString();
    }

    @Override
    public String getUrl() {
        return url;
    }

    @Override
    public Rect getBounds() {
        return mBounds;
    }


    @Nullable
    @Override
    public String getVideoUrl() {
        return videoUrl;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.url);
        dest.writeParcelable(this.mBounds, flags);
        dest.writeString(this.user);
        dest.writeString(this.videoUrl);
    }

    public static final Creator<PhotoInfo> CREATOR = new Creator<PhotoInfo>() {
        @Override
        public PhotoInfo createFromParcel(Parcel source) {
            return new PhotoInfo(source);
        }

        @Override
        public PhotoInfo[] newArray(int size) {
            return new PhotoInfo[size];
        }
    };
}
TestImageLoader 

public class TestImageLoader implements IZoomMediaLoader {

    @Override
    public void displayImage(@NonNull Fragment context,@NonNull String path, final@NonNull MySimpleTarget<Bitmap> simpleTarget) {
        Glide.with(context).load(path).asBitmap() .centerCrop() .diskCacheStrategy(DiskCacheStrategy.SOURCE)
                .error(R.mipmap.ic_launcher)
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
                        simpleTarget.onResourceReady(resource);
                    }
                    @Override
                    public void onLoadStarted(Drawable placeholder) {
                        super.onLoadStarted(placeholder);
                        simpleTarget.onLoadStarted();

                    }

                    @Override
                    public void onLoadFailed(Exception e, Drawable errorDrawable) {
                        super.onLoadFailed(e, errorDrawable);
                        simpleTarget.onLoadFailed(errorDrawable);
                    }
                });
    }

    @Override
    public void onStop(@NonNull Fragment context) {
        Glide.with(context).onStop();

    }

    @Override
    public void clearMemory(@NonNull Context c) {
        Glide.get(c).clearMemory();
    }
}
AntGridView 

public class AntGridView extends GridView {
    public AntGridView(Context context) {
        super(context);
    }

    public AntGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);

        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}
AntListView 

public class AntListView extends ListView{
    public AntListView(Context context) {
        super(context);
    }

    public AntListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);    }
}
 
App 

public class App extends Application {

    public static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = this;

        //日志库初始化
        Logger.addLogAdapter(new AndroidLogAdapter(){
                 @Override
                 public boolean isLoggable(int priority, @Nullable String tag) {
                     //todo 关闭日志 返回 false
                    return super.isLoggable(priority, tag);
                   }
                 }
        );


        //大图浏览初始化
        ZoomMediaLoader.getInstance().init(new TestImageLoader());

        //图片加载库初始化
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this)
                .build();
        ImageLoader.getInstance().init(config);
    }
}
 
BasePresenter 

public interface BasePresenter {

    /**
     * 开始执行
     */
    void start();

    /**
     * 销毁正在的操作,防止内存泄漏
     */
    void onDestroy();
}
 
BaseView

public interface BaseView<T> {
    /**
     *P注入V层
     * @param presenter
     */
    void setPresenter(T presenter);
}
 
MainActivity 

public class MainActivity extends AppCompatActivity  {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);




        ICommentTask task=new CommentTask();
        task.getCommentList("http://39.108.3.12:3000/v1/comment?restaurant_id=32&offset=0&limit=5", new ICallBack() {
            @Override
            public void success(List<Comment> data) {
                Log.d(getLocalClassName(),data.toString());
            }

            @Override
            public void failed(String msg) {

            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

布局

<ListView
    android:id="@+id/lv_comment"
    android:divider="@color/colorPrimaryDark"
    android:dividerHeight="1dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />


<ImageView
    android:id="@+id/user_icon"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@mipmap/ic_launcher" />


<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_toRightOf="@id/user_icon"
    >

    <TextView
        android:id="@+id/user_name"
        android:textColor="@android:color/black"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_below="@id/user_name"
        android:id="@+id/user_comment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_alignParentRight="true"
        android:layout_alignBaseline="@id/user_name"
        android:id="@+id/user_comment_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</RelativeLayout>



<ImageView
    android:id="@+id/user_icon"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:src="@mipmap/ic_launcher" />


<RelativeLayout
    android:id="@+id/layout_comment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_toRightOf="@id/user_icon">

    <TextView
        android:id="@+id/user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black" />

    <TextView
        android:id="@+id/user_comment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/user_name" />

    <TextView
        android:id="@+id/user_comment_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@id/user_name"
        android:layout_alignParentRight="true" />

</RelativeLayout>

<com.jaeger.ninegridimageview.NineGridImageView
    android:id="@+id/user_images"
    android:layout_below="@id/layout_comment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:imgGap="4dp"
    app:showStyle="fill"
    app:singleImgSize="120dp" />

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值