如何正确理解和使用Activity的4种启动模式
关于Activity启动模式的文章已经很多,但有的文章写得过于简单,有的则过于注重细节,本文想取一个折中,只关注最重要和最常用的概念,原理和使用方法,便于读者正确应用。
Activity的启动模式有4种,分别是standard.singleTop. SingleTask. singleInstance,可以在AndroidMainifest.xml文件中指定每一个Activity的启动模式。一个Android应用一般都会有多个Activity,系统会通过任务栈来管理这些Activity,栈是一种后进先出的集合,当前的Activity就在栈顶,按返回键,栈顶Activity就会退出。Activity启动模式不同,系统通过任务栈管理Activity的方式也会不同,以下将分别介绍。
1 Standard模式
Standard模式是Android的默认启动模式,你不在配置文件中做任何设置,那么这个Activity就是standard模式,这种模式下,Activity可以有多个实例,每次启动Activity,无论任务栈中是否已经有这个Activity的实例,系统都会创建一个新的Activity实例,以下是实验验证。
新建一个FirstActivity,用一个Button去启动它本身:
发现每次都会启动一个新的FristActivity, Log信息如下
什么时候用standard模式呢?standartd模式是activity的默认模式,大部分情况下,都应该使用这种模式,也就是在配置文件中什么都不用做,当确实有特殊需求时,再考虑其他模式。
2 SingleTop模式
SingleTop模式和standard模式非常相似,主要区别就是当一个singleTop模式的Activity已经位于任务栈的栈顶,再去启动它时,不会再创建新的实例,如果不位于栈顶,就会创建新的实例,现在把配置文件中FirstActivity的启动模式改为SingleTop,我们的应用只有一个Activity,FirstActivity自然处于任务栈的栈顶。
当应用第一次启动后,我们再按Button去启动新的FirstActivity,发现Log信息中不再打印onCreate函数,说明不再创建新的FirstActivity实例。
这里有一个新的问题,对于每次启动Activity,我们该如何分别处理。答案就是onNewIntent()函数,虽然系统不会调用onCreat(),但会调用onNewIntent,我们可以在这个函数做相应的处理。
当一个Activity已经在栈顶,但依然有可能启动它,而你又不想产生新的Activity实例,此时就可以用singleTop模式。例如,一个搜索Activity,可以输入搜索内容,也可以产生搜索结果,此时就可以用singleTop模式,不会用户每次搜索都会产生一个实例。
3 SingleTask模式
SingleTask模式的Activity在同一个Task内只有一个实例,如果Activity已经位于栈顶,系统不会创建新的Activity实例,和singleTop模式一样。但Activity已经存在但不位于栈顶时,系统就会把该Activity移到栈顶,并把它上面的activity出栈。修改上面的程序,新建一个SecondActivity,将FirstActivity设置为singleTask启动模式,并让它启动SecondActivity,再让SecondActivity来启动FirstActivity。
Log信息如下
当SecondActivity启动FirstActivity时,并不会调用FirstActivity的onCreate函数,但会调用onNewIntent函数,同时会调用SecondActivity的onDestroy函数,SecondActivity实例被销毁。
singleTask模式和前面两种模式的最大区别就是singleTask模式是任务内单例的,所以我们是否设定Activity为singleTask模式,就是看我们activity是否需要单例,例如你的某个Activity
里面有一个列表,如果有多个实例,有可能导致用户看到的列表不一致,有的Activity需要经常启动,如果每次都创建实例,会导致占用资源过多,这些情况都可以使用singleTask模式,但启动singleTask模式的Activity会导致任务栈内它上面的Activity被销毁,有可能会影响用户体验,使用时要注意。
4 SingleInstance模式
singleInstance模式也是单例的,但和singleTask不同,singleTask只是任务栈内单例,系统里是可以有多个singleTask Activity实例的,而singleInstance Activity在整个系统里只有一个实例,启动一singleInstanceActivity时,系统会创建一个新的任务栈,并且这个任务栈只有他一个Activity。
SingleInstance模式并不常用,如果我们把一个Activity设置为singleInstance模式,你会发现它启动时会慢一些,切换效果不好,影响用户体验。它往往用于多个应用之间,例如一个电视launcher里的Activity,通过遥控器某个键在任何情况可以启动,这个Activity就可以设置为singleInstance模式,当在某应用中按键启动这个Activity,处理完后按返回键,就会回到之前启动它的应用,不影响用户体验。
以上分析了Activity的4种启动模式,将Activity设置为哪种启动模式并没有标准答案,有时候,你可能发现将某个Activity设置为一种启动模式或者另一种启动模式,并没有明显区别,而具体的评判标准就是看哪种模式更满足应用功能,更有利于用户体验。
本文介绍了Android自定义View仿IOS圆盘时间选择器,非常实用,有兴趣的同学可以看看通过自定义view实现仿iOS实现滑动两端的点选择时间的效果
效果图
自定义的view代码
代码如下 | 复制代码 |
publicclassRing_Slide2extendsView { privatestaticfinaldoubleRADIAN =180/ Math.PI; privateintmax_progress;// 设置最大进度 privateintcur_progress;//设置锚点1当前进度 privateintcur_progress2;//设置锚点2进度 privateintbottom_color;//设置底色 privateintcircle_color;//设置圆的颜色(锚点) privateintslide_color;//设置滑动过的颜色 privatefloatring_width;//圆环的宽度 privatedoublecur_Angle;//当前锚点1旋转角度 privatedoublecur_Angle2;//当前锚点2的旋转角度 privatefloatring_Radius;//圆环的半径 privatefinalint[] arrColorCircle =newint[]{0xFFFFde37,0xFFFFa400}; privateintmain_width;//圆的宽度 privatefloatmWheelCurX, mWheelCurY;//圆的位置 privatefloatmWheelCurX2, mWheelCurY2;//圆2的位置 privatePaint circle_Paint;//圆环的画笔 privatePaint select_Paint;//选中的画笔 privatePaint dot1;//圆点1 privatePaint dot2;//圆点2 privateContext context; privateOnSeekBarChangeListener changeListener,changeListener2; publicRing_Slide2(Context context) { this(context,null); } publicRing_Slide2(Context context, AttributeSet attrs) { this(context, attrs,0); } publicRing_Slide2(Context context, AttributeSet attrs,intdefStyleAttr) { super(context, attrs, defStyleAttr); this.context=context; initAttrs(attrs,defStyleAttr); initPadding(); //初始化画笔 initPaints(); } //初始化属性 privatevoidinitAttrs(AttributeSet attrs,intdefStyle){ TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.Cricle_slide, defStyle,0); max_progress=typedArray.getInt(R.styleable.Cricle_slide_max_progress,720); cur_progress=typedArray.getInt(R.styleable.Cricle_slide_cur_progress,420); cur_progress2=typedArray.getInt(R.styleable.Cricle_slide_cur_progress2,540); if(cur_progress > max_progress) cur_progress = max_progress; if(cur_progress2 > max_progress) cur_progress2 = max_progress; Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.select_sun_bg2); main_width= bitmap.getWidth(); ring_width=typedArray.getFloat(R.styleable.Cricle_slide_Ring_Width,main_width); bottom_color=typedArray.getColor(R.styleable.Cricle_slide_bottom_color,getColor(R.color.select_main_bg_color)); circle_color=typedArray.getColor(R.styleable.Cricle_slide_circle_color,getColor(R.color.duration)); slide_color=typedArray.getColor(R.styleable.Cricle_slide_slide_color,getColor(R.color.time)); typedArray.recycle(); } //初始化边距 privatevoidinitPadding(){ intpaddingLeft = getPaddingLeft(); intpaddingTop = getPaddingTop(); intpaddingRight = getPaddingRight(); intpaddingBottom = getPaddingBottom(); intpaddingStart =0, paddingEnd =0; if(Build.VERSION.SDK_INT >=17) { paddingStart = getPaddingStart(); paddingEnd = getPaddingEnd(); } intmaxPadding = Math.max(paddingLeft, Math.max(paddingTop, Math.max(paddingRight, Math.max(paddingBottom, Math.max(paddingStart, paddingEnd))))); setPadding(maxPadding, maxPadding, maxPadding, maxPadding); } privatevoidinitPaints(){ /* 圆环的画笔 */ circle_Paint=new Paint(Paint.ANTI_ALIAS_FLAG); circle_Paint.setAntiAlias(true); circle_Paint.setColor(bottom_color); circle_Paint.setStyle(Paint.Style.STROKE); circle_Paint.setStrokeWidth(ring_width); /* 选中区域的画笔 */ select_Paint=new Paint(Paint.ANTI_ALIAS_FLAG); select_Paint.setShader(new SweepGradient(0, 0, arrColorCircle, null)); /*select_Paint.setColor(circle_color);*/ select_Paint.setAntiAlias(true); select_Paint.setStyle(Paint.Style.STROKE); select_Paint.setStrokeWidth(ring_width); // 画锚点 dot1 = new Paint(Paint.ANTI_ALIAS_FLAG); dot1.setColor(circle_color); dot1.setAntiAlias(true); dot1.setStyle(Paint.Style.FILL); // 画锚点2 dot2 = new Paint(Paint.ANTI_ALIAS_FLAG); dot2.setColor(slide_color); dot2.setAntiAlias(true); dot2.setStyle(Paint.Style.FILL); } //获取宽度 private float getDimen(int dimenId) { return getResources().getDimension(dimenId); } //获取颜色 @TargetApi(Build.VERSION_CODES.M) private int getColor(int colorId) { final int version = Build.VERSION.SDK_INT; if (version >= 23) { return getContext().getColor(colorId); } else { return ContextCompat.getColor(getContext(), colorId); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.setalarm_colock_bg); int height = bitmap.getHeight()+main_width*2; int width = bitmap.getWidth()+main_width*2; int min = Math.min(height, width); setMeasuredDimension(min,min); initposition(); } private void initposition(){ //转换为360度 cur_Angle=(double) cur_progress / max_progress*360.0; cur_Angle2=(double)cur_progress2 / max_progress*360.0; //计算初始化旋转的角度 double cos = -Math.cos(Math.toRadians(cur_Angle)); double cos2 = -Math.cos(Math.toRadians(cur_Angle2)); //根据旋转的角度来确定位置 MakeCurPosition(cos); MakeCurPosition2(cos2); //确定圆环的半径 ring_Radius=(getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - ring_width) / 2; } private void MakeCurPosition(double cos){ //根据旋转的角度来确定圆的位置 //确定x点的坐标 mWheelCurX = calcXLocationInWheel(cur_Angle, cos); //确定y点的坐标 mWheelCurY=calcYLocationInWheel(cos); } private void MakeCurPosition2(double cos2){ //根据旋转的角度来确定圆的位置 //确定x点的坐标 mWheelCurX2 = calcXLocationInWheel(cur_Angle2, cos2); //确定y点的坐标 mWheelCurY2=calcYLocationInWheel(cos2); } //确定x点的坐标 private float calcXLocationInWheel(double angle,double cos){ if (angle < 180) { return (float) (getMeasuredWidth() / 2 + Math.sqrt(1 - cos * cos) * ring_Radius); //Math.sqrt正平分根 9-3 } else { return (float) (getMeasuredWidth() / 2 - Math.sqrt(1 - cos * cos) * ring_Radius); } } //确定y点的坐标 private float calcYLocationInWheel(double cos) { return getMeasuredWidth() / 2 + ring_Radius * (float) cos; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float left = getPaddingLeft() + ring_width / 2; float top = getPaddingTop() + ring_width / 2; float right = canvas.getWidth() - getPaddingRight() - ring_width / 2; float bottom = canvas.getHeight() - getPaddingBottom() - ring_width / 2; float centerX = (left + right) / 2; float centerY = (top + bottom) / 2; float wheelRadius = (canvas.getWidth() - getPaddingLeft() - getPaddingRight()) / 2 - ring_width / 2; canvas.drawCircle(centerX, centerY, wheelRadius, circle_Paint); //画选中区域 // canvas.drawArc(new RectF(left, top, right, bottom), (float) (Math.PI * RADIAN + Math.acos(cur_Angle) * RADIAN), (float) (Math.abs(cur_Angle-cur_Angle2)), false, select_Paint); Log.i("TAG","第一个的角度="+cur_Angle); Log.i("TAG","第一个的角度2="+cur_Angle2); float begin=0; //圆弧的起点位置 float stop=0; if(cur_Angle>180 && cur_Angle>cur_Angle2 ){ //180 -- 360 begin=(float) (-Math.abs(cur_Angle-360)-90); stop=(float) Math.abs(Math.abs(cur_Angle-360)+cur_Angle2); Log.i("TAG","begin="+begin); Log.i("TAG","stop="+stop); }else if(cur_Angle>cur_Angle2){ begin=(float) cur_Angle-90; stop=(float)(360-(cur_Angle-cur_Angle2)); }else { begin=(float) cur_Angle-90; stop=(float) Math.abs(cur_Angle-cur_Angle2); } canvas.drawArc(new RectF(left, top, right, bottom), begin,stop, false, select_Paint); //画锚点 画圆 canvas.drawCircle(mWheelCurX, mWheelCurY, ring_width/2, dot1); //画锚点 画圆 canvas.drawCircle(mWheelCurX2, mWheelCurY2, ring_width/2, dot2); Log.i("TAG","锚点1Y"+mWheelCurY+"锚点1X"+mWheelCurX); Log.i("TAG","锚点2Y"+mWheelCurY2+"锚点1X"+mWheelCurX2); } @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); int flag=0; //判断是否触控到两个点中的其中某个点 if(isMovedot2(x,y)){ flag=2; }else if(isMovedot1(x,y)){ flag=1; } /* if(isMovedot1(x,y)){ flag=1; }else if(isMovedot2(x,y)){ flag=2; }*/ if(event.getAction()==MotionEvent.ACTION_MOVE || isMovedot1(x,y) ==true|| isMovedot2(x,y)==true){ Log.i("TAG","进入X="+x+"进入Y="+y); //通过触摸点算出cos角度值 floatcos = calculateCos(x, y); // 通过反三角函数获得角度值 doubleangle;//获取滑动的角度 if(x < getWidth() /2) {// 滑动超过180度 angle = Math.PI * RADIAN + Math.acos(cos) * RADIAN;//通过计算得到滑动的角度值 }else{// 没有超过180度 angle = Math.PI * RADIAN - Math.acos(cos) * RADIAN;//PI 周长比直径 返回弧角度的余弦值 } if(flag==1){ cur_Angle=angle; cur_progress=getSelectedValue(cur_Angle); MakeCurPosition(cos); if(changeListener !=null) { changeListener.onChanged(this, cur_progress); } }elseif(flag==2){ cur_Angle2=angle; cur_progress2=getSelectedValue(cur_Angle2); MakeCurPosition2(cos); if(changeListener2 !=null) { changeListener2.onChanged(this, cur_progress2); } } invalidate(); returntrue; }else{ returnsuper.onTouchEvent(event); } } privatebooleanisMovedot1(floatx,floaty){ floatdot1x = Math.abs(mWheelCurX - x); floatdot1y = Math.abs(mWheelCurY - y); if(dot1x<30&& dot1y<30){ returntrue; }else{ returnfalse; } } privatebooleanisMovedot2(floatx,floaty){ floatdot1x = Math.abs(mWheelCurX2 - x); floatdot1y = Math.abs(mWheelCurY2 - y); if(dot1x<30&& dot1y<30){ returntrue; }else{ returnfalse; } } //拿到切斜角的cos值 privatefloatcalculateCos(floatx,floaty){ floatwidth = x - getWidth() /2; floatheight = y - getHeight() /2; floatslope = (float) Math.sqrt(width * width + height * height); returnheight / slope; } privateintgetSelectedValue(doublemCurAngle) {//角度转进度 returnMath.round(max_progress * ((float) mCurAngle /360));//四舍五入 } publicvoidsetOnSeekBarChangeListener(OnSeekBarChangeListener listener) { changeListener = listener; } publicvoidsetOnSeekBarChangeListener2(OnSeekBarChangeListener listener) { changeListener2 = listener; } publicvoidinitRadian(intpro1,intpro2){ this.cur_progress=pro1; this.cur_progress2=pro2; invalidate(); } publicinterfaceOnSeekBarChangeListener { voidonChanged(Ring_Slide2 seekbar,intcurValue); } } |
自定义stayle样式,在values下新建sttrs.xml文件
代码如下 | 复制代码 |
//设置最大进度
//设置当前进度
//设置当前进度
//设置底色
//设置圆的颜色
//设置滑动的颜色
//圆环的宽度 (dimension是代表尺寸值)
|
这篇文章主要介绍了Android编程之ActionBar Tabs用法,结合实例形式分析了ActionBar Tabs的功能及Tab切换不同的Fragment的相关实现技巧,需要的朋友可以参考下
这里主要实现用Tab切换不同的Fragment,点击View显示or隐藏ActionBar,把ActionBar 设为透明,使界面更加友好,详细代码见资源里的ActionBarTabs。
ActionBar Tab主要用于Fragment之间的切换,其必须要设置ActionBar.TabListener,详细代码如下
ActionBarActivity.Java:
代码如下 | 复制代码 |
importandroid.app.ActionBar; importandroid.app.Activity; importandroid.app.FragmentTransaction; importandroid.app.ActionBar.Tab; importandroid.os.Bundle; importandroid.os.CountDownTimer; importandroid.view.MotionEvent; importandroid.view.Window; publicclassActionBarActivityextendsActivity { /** Called when the activity is first created. */ @Override publicvoidonCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //使ActionBar变得透明 requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); setContentView(R.layout.main); finalActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // remove the activity title to make space for tabs actionBar.setDisplayShowTitleEnabled(false); AFragment aFragment =newAFragment(); actionBar.addTab(actionBar.newTab().setText("Tab-A") .setTabListener(newListenerA(aFragment))); BFragment bFragment =newBFragment(); actionBar.addTab(actionBar.newTab().setText("Tab-B") .setTabListener(newListenerB(bFragment))); } //点击显示or隐藏ActionBar publicbooleanonTouchEvent(MotionEvent event){ ActionBar bar = getActionBar(); switch(event.getAction()){ caseMotionEvent.ACTION_UP: if(bar.isShowing()) bar.hide(); elsebar.show(); break; default: break; } returntrue; } privateclassListenerAimplementsActionBar.TabListener { privateAFragment mFragment; // Called to create an instance of the listener when adding a new tab publicListenerA(AFragment fragment) { mFragment = fragment; } publicvoidonTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment, mFragment,null); } publicvoidonTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } publicvoidonTabReselected(Tab tab, FragmentTransaction ft) { // do nothing } } } privateclassListenerBimplementsActionBar.TabListener { privateBFragment mFragment; // Called to create an instance of the listener when adding a new tab publicListenerB(BFragment fragment) { mFragment = fragment; } publicvoidonTabSelected(Tab tab, FragmentTransaction ft) { ft.add(R.id.fragment, mFragment,null); } publicvoidonTabUnselected(Tab tab, FragmentTransaction ft) { ft.remove(mFragment); } publicvoidonTabReselected(Tab tab, FragmentTransaction ft) { // do nothing } } } } |
其中涉及到两个Fragment,在前面Fragment的笔记中讲过,这里就不再赘述。类AFragment实现如下,BFragment实现与这类似:
代码如下 | 复制代码 |
publicclassAFragmentextendsFragment { publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { returninflater.inflate(R.layout.alayout, container,false); } } |
小编给大家推荐的这篇文章介绍了 Android编程之交互对话框实例浅析,非常实用,有兴趣的同学快来看看吧!
1. 在Android SDK中,虽然有许多的窗口,有些类似Modeless的窗口、有些类似于前端Force Focus的窗口,但真正具有交互功能的则为AlertDialog对话窗口。
代码如下 | 复制代码 |
newAlertDialog.Builder(EX03_12.this) .setTitle(R.string.app_about) .setMessage(R.string.app_about_msg) .setPositiveButton(R.string.str_ok, newDialogInterface.OnClickListener() { publicvoidonClick(DialogInterface dialoginterface,inti) { } }).show(); |
这里仅是有一个确定按钮,还可以添加其他的按钮和图标,可以参照Android文档。
2.提到AlertDialog,自然就会想到Toast。Toast就是一个简短的小信息,可以提示音量大小的调整等。对程序员来说,它也是一个非常好用的Debug工具。
代码如下 | 复制代码 |
/*使用系统标准的 makeText()方式来产生Toast讯息*/ Toast.makeText( EX04_03.this,String,Toast.LENGTH_LONG).show(); |
第三个参数可以是LENGTH_LONG或LENGTH_SHORT,前者表示时间长,后者较短。当然,也可以使用重写的Toast对象的方法,自己定义Toast显示的Layout。
相关文章
- 这篇文章主要介绍了Tomcat配置及如何在Eclipse中启动,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-04
- 有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
- ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。  ...2017-07-06
- 这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
- 神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
- 这篇文章主要介绍了Postgresl 如何选择正确的关闭模式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-18
使用insertAfter()方法在现有元素后添加一个新元素
复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31jQuery 1.9使用$.support替代$.browser的使用方法
jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31使用percona-toolkit操作MySQL的实用命令小结
1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24- 大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
如何使用php脚本给html中引用的js和css路径打上版本号
在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24- C#注释的一些使用方法浅谈,需要的朋友可以参考一下...2020-06-25
- 一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
php-fpm 启动报please specify user and group other than root, pool ‘default’
本文章来给大家介绍关于php-fpm 启动报please specify user and group other than root, pool ‘default’的解决办法。 安装PHP ,配置fpm 成功后启动发现报错: St...2016-11-25安装和使用percona-toolkit来辅助操作MySQL的基本教程
一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24- 这篇文章主要介绍了IDEA 2021.2 启动报错及激活教程,文章开头给大家介绍了idea2021最新激活方法,关于idea2021启动报错的问题小编也给大家介绍的非常详细,需要的朋友可以参考下...2021-10-15
- 目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30
- 在程序执行中会遇到启动本软件的exe问,或者启用其它的exe文件,已达到执行某些操作的作用。下面是两种最常见的启动exe文件。...2020-06-25
- 基本思路: 通过使用jquery选择器得到对应表单的jquery对象,然后使用attr方法修改对应的action 示例程序一: 默认情况下,该表单会提交到page_one.html 点击button之后,表单的提交地址就会修改为page_two.html 复制...2014-06-07