代码地址如下:
http://www.demodashi.com/demo/11212.html

前言

本案例已经开源!如果你想免费下载,可以访问我的Github,所有案例均在上面,只求给个star。当然愿意支付小小金额请我喝茶也行(大学穷狗-.-)

一、准备工作

  • 使用Android Studio开发
  • 微信和QQ第三方sdk,需要自行申请(这个简单)
  • 本案例使用干活集中营提供的api,使用MVp+Material Design作为主体架构进行开发
  • 体验完整功能,点击下载APK

二、程序实现

目录结构

目录结构如下,我按照功能分包:

实现思路

整体架构--MVP+Material

  • 首先你得了解MVP架构在android中的使用,如果你还不了解,可以阅读我的这篇文章
  • 如果你不熟悉Material可以读官方文档

重点代码分析

如果讲述整个App,估计一篇文章说不清楚。那我干脆取其中一条线来分析。

下面主要分析文章列表--文章详情--文章分享

主页文章列表

这里只选择Android文章模块进行介绍:

GankContract

public interface GankContract {
interface View extends BaseView<Presenter>{
//错误
void showError();
//正在加载
void showLoading();
//停止加载
void Stoploading();
//显示数据列表
void showResult(ArrayList<GankNews.Question> list);
//网络错误
void showNotNetError(); }
interface Presenter extends BasePresenter{
// 请求数据
void loadPosts(int PagerNum, boolean cleaing);
//刷新数据
void reflush();
//加载更多
void loadMore(int PagerNum);
//显示详情
void StartReading(int positon);
//随便看看
void LookAround();
}
}

GankFragment

Fragment的内容主要是文章列表,我们只分享重点:

//下拉刷新实现
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
boolean isScrollState=false;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
LinearLayoutManager manager= (LinearLayoutManager) recyclerView.getLayoutManager();
//没有滚动时候
if (newState==RecyclerView.SCROLL_STATE_IDLE){
//获的最后一个可见的item
int lastVisibilityItem=manager.findLastCompletelyVisibleItemPosition();
int totalItemCount=manager.getItemCount(); //判断是否滚动到底部并且是向下滑动
if (lastVisibilityItem==(totalItemCount-1)&&isScrollState){
presenter.loadMore(1);
}
} } //通知Presenter加载数据和设置item点击事件
@Override
public void showResult(ArrayList<GankNews.Question> list) {
if (adapter==null){
Log.i(TAG, "showResult: "+list.size());
adapter=new GankNewsAdapter(list,getContext());
adapter.setItemOnClickListener(new OnRecyclerViewOnClickListener() {
@Override
public void onItemClick(View v, int position) {
presenter.StartReading(position);
} @Override
public void onItemLongClick(View v, int position) { }
});
recyclerView.setAdapter(adapter);
}else {
adapter.notifyDataSetChanged();
}
}

GankPresenter

同样只分析重点代码:

//根据当前页数加载列表数据
@Override
public void loadPosts(int PagerNum, final boolean cleaing) {
CurrentPagerNum=PagerNum;
if (cleaing) {
view.showLoading();
}
if (Network.networkConnected(context)) {
model.load(Api.Gank_Android + PagerNum, new OnStringListener() {
@Override
public void onSuccess(String result) {
try {
// Log.i(TAG, "gankpresenter.model.load.result"+result);
GankNews news = gson.fromJson(result, GankNews.class);
//contenvalues只能存储基本类型的数据,像string,int之类的,不能存储对象这种东西,而HashTable却可以存储对象。
// ContentValues values = new ContentValues();
if (cleaing) {
list.clear();
}
for (GankNews.Question item : news.getResults()) {
/**
* 1.数据库查重:首先检测数据库中是否已经储存过该条数据
* 2:因为每次重启后都是在网络上重新下载数据 如果是数据库已经存在的数据则不会重新加载,也导致了这些数据当前id值为空
* ,所有要绑定队友的id值.
*/
if (!queryIfIdExists(item.get_id())){
DbLiteOrm.insert(item, ConflictAlgorithm.Replace);
}else {
ArrayList<GankNews.Question> ganklist=App.DbLiteOrm.query(new QueryBuilder<GankNews.Question>(GankNews.Question.class)
.where(GankNews.Question.COL_ID+"=?",new String[]{item.get_id()}));
GankNews.Question gankitem=ganklist.get(0);
item.setId(gankitem.getId());
}
list.add(item);
}
view.showResult(list);
}catch (JsonSyntaxException e){
view.showError();
}
view.Stoploading();
} @Override
public void onError(VolleyError error) {
view.Stoploading();
view.showError();
}
});
} else {
//更新列表缓存 因为详情页都是用webView呈现 所以缓存content为空
if (cleaing){
QueryBuilder query=new QueryBuilder(GankNews.Question.class);
query.appendOrderDescBy("id");
query.limit(0,10*CurrentPagerNum);
list.addAll(DbLiteOrm.<GankNews.Question>query(query));
view.showResult(list);
}else {
view.showNotNetError();
}
}
} //判断数据库是否已经存在
public boolean queryIfIdExists(String _id){
ArrayList<GankNews.Question> questionArrayList=App.DbLiteOrm.query(new QueryBuilder(GankNews.Question.class)
.where(GankNews.Question.COL_ID+"=?",new String[]{_id}));
if (questionArrayList.size()==0){
return false;
}
return true;
} //传递当前点击item的信息,进入详情阅读
@Override
public void StartReading(int positon) {
//每个item就是一组数据
GankNews.Question item=list.get(positon);
Intent intent = new Intent(context, DetailActivity.class);
intent.putExtra("type", BeanTeype.TYPE_Gank);
intent.putExtra("id",list.get(positon).getId());
int id=list.get(positon).getId();
Log.i(TAG, "StartReading: "+id);
intent.putExtra("_id", list.get(positon).get_id());
intent.putExtra("url",list.get(positon).getUrl());
intent.putExtra("title", list.get(positon).getDesc());
if (item.getImages()==null){
intent.putExtra("imgUrl", "");
}else {
intent.putExtra("imgUrl", list.get(positon).getImages().get(0));
}
/**
* Content的startActivity方法,需要开启一个新的task。如果使用 Activity的startActivity方法,
* 不会有任何限制,因为Activity继承自Context,重载了startActivity方法。
*/
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} //随便看看 随机选取
@Override
public void LookAround() {
if (list.isEmpty()){
view.showError();
return;
}
StartReading(new Random().nextInt(list.size()));
}

GankNewsAdapter

因为文章分两种:有图和无图。所有要进行分类加载

//判断是否有图和是否是底部加载item
@Override
public int getItemViewType(int position) {
if (position==getItemCount()-1){
return TYPE_FOOTER;
}if (list.get(position).getImages()==null){
return TYPE_NO_IMG;
}
return TYPE_NORMTAL;
} //根据type加载不同ViewHolder
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case TYPE_NORMTAL:
return new NormalViewHolder(inflater.inflate(R.layout.home_list_item_layout,parent,false),listener);
case TYPE_FOOTER:
return new FooterViewHolder(inflater.inflate(R.layout.list_footer,parent,false));
case TYPE_NO_IMG:
return new NoImageViewHolder(inflater.inflate(R.layout.home_list_item_without_image,parent,false),listener);
}
return null;
} //使用Glide加载图片。无图则不加载
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (!(holder instanceof FooterViewHolder)){
GankNews.Question item=list.get(position);
if (item!=null){ if (holder instanceof NormalViewHolder){
Glide.with(context)
.load(item.getImages().get(0))
.asBitmap()
.placeholder(R.mipmap.loading)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.error(R.mipmap.loading)
.centerCrop()
.into(((NormalViewHolder) holder).imageView);
((NormalViewHolder) holder).textView.setText(item.getDesc());
}else if (holder instanceof NoImageViewHolder){
((NoImageViewHolder) holder).textViewNoImg.setText(item.getDesc());
}
}
} }

详情页

DetailActivity

 @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frame);
if (savedInstanceState!=null){
detailFragment= (DetailFragment) getSupportFragmentManager().getFragment(savedInstanceState,"detailFragment");
}else {
detailFragment=DetailFragment.newInstance();
getSupportFragmentManager().beginTransaction().replace(R.id.container,detailFragment).commit();
}
//获取列表传过来的具体item数据
Intent intent=getIntent();
DetailPresenter presenter=new DetailPresenter(detailFragment,DetailActivity.this);
presenter.setType((BeanTeype) intent.getSerializableExtra("type"));
presenter.setId(intent.getIntExtra("id",1));
presenter.set_id(intent.getStringExtra("_id"));
presenter.setTitle(intent.getStringExtra("title"));
presenter.setUrl(intent.getStringExtra("url"));
presenter.setImgUrl(intent.getStringExtra("imgUrl"));
}

DetailContract

public class DetailContract {
interface Presenter extends BasePresenter{
/**
* 流浪器中打开
* 复制文本
* 复制连接
* 添加收藏或取消收藏
* 查询是否收藏
* 请求数据
* 分享到QQ
* 分享到微信
* 分享到朋友圈
* 分享到微信收藏
*/
void openInBrower();
void copyText();
void copyLink();
void addToOrDeleteFromBookMarks();
boolean queryIsBooksMarks();
void requestData();
void shareArticleToQQ(final MyQQListener listener);
void shareArticleToWx();
void shareArticleToWxCommunity();
void shareArticleToWxCollect();
}
interface View extends BaseView<Presenter> {
// 显示正在加载
void showLoading();
// 停止加载
void stopLoading();
// 显示加载错误
void showLoadingError();
// 显示分享时错误
void showSharingError();
// 正确获取数据后显示内容
// void showResult(String result);
// // 对于body字段的消息,直接接在url的内容
void showResultWithoutBody(String url);
// 设置顶部大图
void showCover(String url);
// 设置标题
void setTitle(String title);
// 设置是否显示图片
void setImageMode(boolean showImage);
// 用户选择在浏览器中打开时,如果没有安装浏览器,显示没有找到浏览器错误
void showBrowserNotFoundError();
// 显示已复制文字内容
void showTextCopied();
// 显示文字复制失败
void showCopyTextError();
// 显示已添加至收藏夹
void showAddedToBookmarks();
// 显示已从收藏夹中移除
void showDeletedFromBookmarks();
void showNotNetError(); void shareSuccess();
void shareError();
void shareCancel();
}
}

DetailFragment

详情页主题是使用WebView显示,重点注意好设置属性和正确销毁:

 @Override
public void initView(View view) {
......
//webview设置属性
webview.getSettings().setJavaScriptEnabled(true);
//缩放,设置为不能缩放可以防止页面上出现放大和缩小的图标
webview.getSettings().setBuiltInZoomControls(false);
//缓存
webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
//开启DOM storage API功能
webview.getSettings().setDomStorageEnabled(true);
//开启application Cache功能
webview.getSettings().setAppCacheEnabled(false);
..... } //早onDestroy中销毁WebView的对象
@Override
public void onDestroyView() {
super.onDestroyView();
webview.removeAllViews();
webview.destroy();
webview=null;
}

DetailPresenter

//复制链接地址
@Override
public void copyLink() {
ClipboardManager manager= (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData data=null;
switch (type){
case TYPE_Gank:
data=ClipData.newPlainText("text",url);
}
manager.setPrimaryClip(data);
view.showTextCopied();
} //添加到收藏或者移除收藏
@Override
public void addToOrDeleteFromBookMarks() {
switch (type){
case TYPE_Gank:
GankNews.Question gank= App.DbLiteOrm.queryById(id,GankNews.Question.class);
if (queryIsBooksMarks()){
view.showDeletedFromBookmarks();
gank.mark=false;
}else {
view.showAddedToBookmarks();
gank.mark=true;
}
App.DbLiteOrm.update(gank);
break;
case TYPE_Front:
FrontNews.Question front=App.DbLiteOrm.queryById(id,FrontNews.Question.class);
if (queryIsBooksMarks()){
view.showDeletedFromBookmarks();
front.mark=false;
}else {
view.showAddedToBookmarks();
front.mark=true;
}
App.DbLiteOrm.update(front);
break;
case TYPE_IOS:
IosNews.Question ios=App.DbLiteOrm.queryById(id,IosNews.Question.class);
if (queryIsBooksMarks()){
view.showDeletedFromBookmarks();
ios.mark=false;
}else {
view.showAddedToBookmarks();
ios.mark=true;
}
App.DbLiteOrm.update(ios);
}
} //查询是否已经收藏
@Override
public boolean queryIsBooksMarks() {
if (_id ==null || type==null){
view.showLoadingError();
return false;
}
//true为已经收藏 false未收藏
switch (type){
case TYPE_Gank:
GankNews.Question gank= App.DbLiteOrm.queryById(id,GankNews.Question.class);
OrmLog.i(TAG,gank);
boolean isMark=gank.mark;
if (isMark){
return true;
}else {
return false;
}
case TYPE_Front:
FrontNews.Question front=App.DbLiteOrm.queryById(id,FrontNews.Question.class);
if (front.mark){
return true;
}else {
return false;
}
case TYPE_IOS:
Log.i(TAG, "queryIsBooksMarks: "+id);
IosNews.Question ios=App.DbLiteOrm.queryById(id,IosNews.Question.class);
OrmLog.i(TAG,ios);
if (ios.mark){
return true;
}else {
return false;
}
}
return false;
} //分享到QQ
@Override
public void shareArticleToQQ(MyQQListener listener) {
//title == desc
if (TextUtils.isEmpty(imgUrl)){
ShareSingleton.getInstance().shareToQQ((Activity) context,url,"推荐给你一篇文章",title, R.string.app_name, QQShare.SHARE_TO_QQ_FLAG_QZONE_ITEM_HIDE,listener);
}else {
ShareSingleton.getInstance().shareToQQ((Activity) context,url,"推荐给你一篇文章",title,imgUrl,R.string.app_name, QQShare.SHARE_TO_QQ_FLAG_QZONE_ITEM_HIDE,listener);
}
} //分享到微信
@Override
public void shareArticleToWx() {
//title == desc
ShareSingleton.getInstance().shareWebToWx(url,"",title,true);
} //分享到朋友圈
@Override
public void shareArticleToWxCommunity() {
//title == desc
ShareSingleton.getInstance().shareWebToWx(url,"",title,false);
} //分享到微信收藏
@Override
public void shareArticleToWxCollect() {
//title == desc
ShareSingleton.getInstance().shareWebToWxCollect(url,"干货",title);
}

ShareSingleton

关于微信和QQ分享的具体方法还得参考官方文章,我这里提出我自己写好的分享单例类

public class ShareSingleton {

    private Tencent mTencent;
public static IWXAPI api; private static final int THUMB_SIZE = 150; //单例模式
private ShareSingleton() {
}
public static final ShareSingleton getInstance(){
return Singleton.INSTANCE;
}
private static class Singleton{
private static final ShareSingleton INSTANCE=new ShareSingleton();
} /**
* 图文分享 图片来源网络
* !! 分享操作要在主线程中完成
* @param activity
* @param targetUrl 这条分享消息被好友点击后的跳转URL。
* @param shareTitle 分享的标题, 最长30个字符。
* @param shareSummary 分享的消息摘要,最长40个字。
* @param netImgUrl 可填 分享图片的URL或者本地路径
* @param appName 手Q客户端顶部,替换“返回”按钮文字,如果为空,用返回代替
* @param shareToQQExtInt 额外选项 是否自动打开分享到QZone的对话框
* @param listener 分享回调接口
*/
public void shareToQQ(Activity activity,String targetUrl,String shareTitle,String shareSummary,
@Nullable String netImgUrl,@StringRes int appName,int shareToQQExtInt,MyQQListener listener){
if (mTencent==null){
mTencent=Tencent.createInstance(Constants.QQ_APP_ID,activity.getApplicationContext());
}
final Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL,targetUrl);
params.putString(QQShare.SHARE_TO_QQ_TITLE, shareTitle);
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, shareSummary );
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, netImgUrl);
params.putString(QQShare.SHARE_TO_QQ_APP_NAME,activity.getString(appName));
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, shareToQQExtInt);
mTencent.shareToQQ(activity, params, listener);
} /**
* 文章分享 无图
* !! 分享操作要在主线程中完成
* @param activity
* @param targetUrl 这条分享消息被好友点击后的跳转URL。
* @param shareTitle 分享的标题, 最长30个字符。
* @param shareSummary 分享的消息摘要,最长40个字。
* @param appName 手Q客户端顶部,替换“返回”按钮文字,如果为空,用返回代替
* @param shareToQQExtInt 额外选项 是否自动打开分享到QZone的对话框
* @param listener 分享回调接口
*/
public void shareToQQ(Activity activity,String targetUrl,String shareTitle,String shareSummary
,@StringRes int appName,int shareToQQExtInt,MyQQListener listener){
if (mTencent==null){
mTencent=Tencent.createInstance(Constants.QQ_APP_ID,activity.getApplicationContext());
}
final Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL,targetUrl);
params.putString(QQShare.SHARE_TO_QQ_TITLE, shareTitle);
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, shareSummary );
params.putString(QQShare.SHARE_TO_QQ_APP_NAME,activity.getString(appName));
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, shareToQQExtInt);
mTencent.shareToQQ(activity, params, listener);
} /**
* 分享文章到微信/朋友圈
* @param webUrl
* @param webTitle
* @param webDesc
* @param isShareFriend
*/
public void shareWebToWx(@NonNull String webUrl,String webTitle,String webDesc,boolean isShareFriend){
// 注册操作也可以写死在Application中
// 通过WXAPIFactory工厂,获取IWXAPI的实例
api=WXAPIFactory.createWXAPI(App.getContext(),Constants.WX_APP_ID,true);
// 将该app注册到微信
api.registerApp(Constants.WX_APP_ID); //初始化一个WXWebpageObject对象,填写url
WXWebpageObject webpag=new WXWebpageObject();
webpag.webpageUrl=webUrl; //用WXWebpageObject对象初始化一个WXMediaMessage对象 填写标题和描述
WXMediaMessage msg=new WXMediaMessage(webpag);
msg.title=webTitle;
msg.description=webDesc; //构造一个Req
SendMessageToWX.Req req=new SendMessageToWX.Req();
req.transaction=buildTransaction("webpage");//transaction 字段用于唯一标识一个请求
req.message= msg;
req.scene=isShareFriend ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline; api.sendReq(req);
} /**
* 分享文章到微信收藏
* @param webUrl
* @param webTitle
* @param webDesc
*/
public void shareWebToWxCollect(@NonNull String webUrl, String webTitle, String webDesc){
// 注册操作也可以写死在Application中
// 通过WXAPIFactory工厂,获取IWXAPI的实例
api=WXAPIFactory.createWXAPI(App.getContext(),Constants.WX_APP_ID,true);
// 将该app注册到微信
api.registerApp(Constants.WX_APP_ID); //初始化一个WXWebpageObject对象,填写url
WXWebpageObject webpag=new WXWebpageObject();
webpag.webpageUrl=webUrl; //用WXWebpageObject对象初始化一个WXMediaMessage对象 填写标题和描述
WXMediaMessage msg=new WXMediaMessage(webpag);
msg.title=webTitle;
msg.description=webDesc; //构造一个Req
SendMessageToWX.Req req=new SendMessageToWX.Req();
req.transaction=buildTransaction("webpage");//transaction 字段用于唯一标识一个请求
req.message= msg;
req.scene=SendMessageToWX.Req.WXSceneFavorite; api.sendReq(req);
}

这篇文章就分析这么多,如果你想了解跟多,欢迎下载源码。主要部分源码都有注释

三、部分运行效果









四、其他补充

如果你有问题可以提交到Github的issue上,也可以给我发邮件。我的邮件是yeshuwei.swy@gmail.com

Android--从零开始开发一款文章阅读APP

代码地址如下:
http://www.demodashi.com/demo/11212.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

Android--从零开始开发一款文章阅读APP的更多相关文章

  1. Android开源实战:使用MVP+Retrofit开发一款文字阅读APP

    文字控 使用MVP+Retrofit开发的一款文艺APP,它是一个非常优美的文字阅读应用,界面基本上符合material design设计规范. 在该项目中,我采用的是MVP架构,该架构目前在Andr ...

  2. 基于WanAndroid开放API实现的文章阅读APP

    简介 基于WanAndroid开放API开发的技术文章阅读App.主要功能包括:首页.体系.项目.公众号.搜索.登录.收藏.夜间模式等. 用到的第三方框架 RxJava RxAndroid Retro ...

  3. 从零开始开发一款app,所想到的

    我在知乎上看到这个问题http://www.zhihu.com/question/27645587.我在阅读了各位大牛的答案后,再加上自己的思考,就有了这篇文章的内容.     从零开始开发一款app ...

  4. 开发一款即时通讯App,从这几步开始

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 " ...

  5. 从零开始开发一款H5小游戏(二) 创造游戏世界,启动发条

    本系列文章对应游戏代码已开源 Sinuous game 上一节介绍了canvas的基础用法,了解了游戏开发所要用到的API.这篇文章开始,我将介绍怎么运用这些API来完成各种各样的游戏效果.这个过程更 ...

  6. 从零开始开发一款H5小游戏(三) 攻守阵营,赋予粒子新的生命

    本系列文章对应游戏代码已开源 Sinuous game. 每个游戏都会包含场景和角色.要实现一个游戏角色,就要清楚角色在场景中的位置,以及它的运动规律,并能通过数学表达式表现出来. 场景坐标 canv ...

  7. 如何开发一款堪比APP的微信小程序(腾讯内部团队分享)

    一夜之间,微信小程序刷爆了行业网站和朋友圈,小程序真的能如张小龙所说让用户"即用即走"吗? 其功能能和动辄几十兆安装文件的APP相比吗? 开发小程序,是不是意味着移动应用开发的一次 ...

  8. [Android游戏开发]八款开源 Android 游戏引擎 (巨好的资源)

    初学Android游戏开发的朋友,往往会显得有些无所适从,他们常常不知道该从何处入手,每当遇到自己无法解决的难题时,又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引 ...

  9. Android商城开发系列(二)——App启动欢迎页面制作

    商城APP一般都会在应用启动时有一个欢迎界面,下面我们来实现一个最简单的欢迎页开发:就是打开商城App,先出现欢迎界面,停留几秒钟,自动进入应用程序的主界面. 首先先定义WelcomeActivity ...

随机推荐

  1. BZOJ 3022 [Balkan2012]The Best Teams(扫描线+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3022 [题目大意] 给定n个球员,第i个球员年龄为AGEi,水平为SKILLi. 没有 ...

  2. [BZOJ3529]数表

    假设$n\leq m$,我们先不考虑$\leq a$的限制 $\sum\limits_{i=1}^n\sum\limits_{j=1}^m\sigma((i,j))=\sum\limits_{T=1} ...

  3. 【动态规划】【线段树】 Codeforces Round #426 (Div. 1) B. The Bakery

    给你一个序列,让你划分成K段,每段的价值是其内部权值的种类数,让你最大化所有段的价值之和. 裸dp f(i,j)=max{f(k,j-1)+w(k+1,i)}(0<=k<i) 先枚举j,然 ...

  4. 【深度搜索+剪枝】POJ2362-Square

    从昨天晚上写到现在,一直在TLE,现在终于剪枝完成了_(:зゝ∠)_ [思路] 深搜:用这类型组合题目最基本的深搜,变量side记录当成已经组成了几条变,sl表示当前在组合的边已经有的长度.如果当前s ...

  5. mysql函数的使用create function myfunction(...

    use test   //必须在某个数据库下面创建 delimiter $ //创建 CREATE FUNCTION myFunction(ln int, ls int)   //参数这里不能加def ...

  6. iOS- dispatch_semaphore和NSOperationQueue并发

    并发:同一个时间内运行多个任务.又叫共行性,是指处理多个同时性活动的能力. 并行:是指两个并发的任务同时发生. 并发不一定并行,并发不一定要同时发生. 举个例子: 有两个快递分别要送到目的地,有以下两 ...

  7. 【docker】解决docker pull镜像 拉取镜像龟速的问题,docker拉取镜像使用阿里云docker镜像加速器

    在docker拉取mysql镜像过程中,出现龟速的问题,解决这个问题的方法: 这个页面 停留了好久好久,依旧没有下载完成. 碰上这种情况 1.先退出Ctrl+C 2.在浏览器上进入阿里云docker库 ...

  8. 【spring cloud】spring cloud中启动eureka集群时候,发生端口已经绑定的报错The Tomcat connector configured to listen on port 8000 failed to start. The port may already be in use or the connector may be misconfigured.

    在分别设置 进行微服务eureka集群启动时候,执行命令行启动jar包时候,报错前面一个端口8000已经被使用,而我这里启动的配置文件中端口号是8001,怎么会导致端口冲突呢?? 但是报错我的端口冲突 ...

  9. 【系统自启动】使用windows自带工具管理开机启动项

    1.windows+R,键入:msconfig 2.进入启动选项卡 3.将不用自启动的选项 取消勾选即可 点击应用,重启电脑即可

  10. HTML 标签的 enctype 属性

    定义和用法 enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码. 默认地,表单数据会编码为 "application/x-www-form-urlencoded" ...