首页 文章 精选 留言 我的

精选列表

搜索[优化],共10000篇文章
优秀的个人博客,低调大师

Flink SQL 功能解密系列 —— 维表 JOIN 与异步优化

引子 流计算中一个常见的需求就是为数据流补齐字段。因为数据采集端采集到的数据往往比较有限,在做数据分析之前,就要先将所需的维度信息补全。比如采集到的交易日志中只记录了商品 id,但是在做业务时需要根据店铺维度或者行业纬度进行聚合,这就需要先将交易日志与商品维表进行关联,补全所需的维度信息。这里所说的维表与数据仓库中的概念类似,是维度属性的集合,比如商品维,地点维,用户维等等。 在流计算中,这是一个典型的 stream-to-table jon 的问题。本文主要讲解在 Flink SQL 中是如何解决这个问题的,用户如何简单上手使用这个功能。 维表 JOIN 语法 由于维表是一张不断变化的表(静态表只是动态表的一种特例)。那如何 JOIN 一张不断变化的表呢?如果用传统的 JOIN 语法SELECT * FROM T JOIN dim_ta

优秀的个人博客,低调大师

LAMP架构下的Web开发概念、流程及优化策略(二)

六、目前流行的PHP框架 应用场景二:M (业务模型,应用者编写) C(业务控制器,应用者编写,由框架控制器自动载入) V(视图,应用者编写,框架自动载入) 现实中复杂应用场景: 1.用户请求:http://domain/blog/list/ 2.分析URL,实例化逻辑控制类blog,执行方法list 3.在控制类news中,又分别实例化业务模型类blog和user,并做相应处理. 4.业务模型类blog,user中,调用数据模型(专用,非M层),对数据进行处理. 5.回到逻辑控制类中,展现视图$this->view->output( ); ※运用中需要注意的地方 •PHP没有持久层,每一次访问请求都是独立运行,建立的模型对象不能持久存在,无法跨访问复用.如果框架/应用的设计过于繁琐,每次装载/初始化都会浪费不少时间. •各层之间的耦合度尽量降到最低,尤其是业务模型和业务逻辑之间要尽量分离.以便日后修改或复用. •PHP本身只有较少功能是抛出异常,大部份是抛出错误(Notice,warning,error),代码编写中应时常对应用环境的正确性做手工检查,不符合条件时手工抛出异常,并设置异常接收器统一处理 •单入口模式 http://domain/index.php?control=blog&action=list http://domain/index.php?control=news&action=read •多入口模式 http://domain/blog.php?action=list http://domain/news.php?action=read •PathInfo模式 http://domain/index.php/blog/list/ http://domain/index.php/news/read/ •Rewrite模式 http://domain/blog/list/ http://domain/news/read/ Rewrite及pathinfo的好处:对搜索引擎友好,对用户更直观 九、数据库抽象层、Active recode •数据库抽象层的作用 减少与具体数据库的底层接触,提供跨数据库平台的访问接口,以实现数据操作与数据库类型的无关性.方便数据库系统的迁移变更. •PHP本身提供的抽象层 Pear::DB(php4),PDO(php5,6) •框架中引入的各种类Active Recode系统 目的:将数据库字段与映射到对象,不用关心具体的SQL语句,只需要操作数据对象及调用相关的方法即可实现数据的CRUD操作。 好处:模型化了数据库,快捷开发,是数据库抽象层的进一步进化。 缺点:对于复杂数据模型的处理较为无力,例如多表连查、子查询。 缺乏灵活性,比如只想要一列数据,却取出了整行。 与数据库字段名的耦合度太高。如通过配置改进,执行效率又打折扣。 难以应付复杂的Web环境。(多种数据库,分布式数据库,缓存系统介入) 十、模板引擎 •为什么引入模板引擎 视图:在web开发中通常就是指前端页面。模板引擎的引入,是为了实现视图层的分离,降低视图与逻辑、模型部份的耦合度。使得前端页面与程序部份可以并行工发、轻松整合的工具 •常见的模板引擎及特点 PHP中常用的模板引擎有Smarty, SmartTemplate 其中smarty提供了强劲的功能,STE则非常轻巧。 两者的核心原理,都是将页面中的变量标签替换成通过assign方法注册的PHP运行变量,并将替换后的页面(“编译”后的页面文件)生成缓存保存在磁盘中。或者提供一定的逻辑控制功能供前端使用。这样即方便将程序和视图分离,使前端设计人员更着重于表现和数据,而不用关心程序上的流程. •缺点 初次加载模板时,因生成缓存,需要额外的处理开销和IO开销 之后加载模板时,会判断模板文件的最后修改时间是否大于生成的缓存文件时间,亦有一定的额外IO开销. ※使用模板引擎的注意事项 八、访问模式 •Qee /FleaPHP (领域设计驱动)•ThinkPHP(大的类库J)•Zend Framework(Pear的OOP版)•Yii•KiwiPHP(工业微内核)•Symfony(配置最简单) 七、WEB中的MVC开发模式 应用场景一: M (数据模型,框架提供) C (控制器,框架实现) V (视图,应用者编写,框架自动载入) 应用者编写的,是供控制器装载的业务处理类 •尽量折分公用组件。 •不要在视图中使用太多的控制语句 就以前的经验来看,简单的if,变量循环输出即已足够。 在视图中加入太多的控制语句会带来的问题,是对设计思想的破坏,因为它打乱了将视图层独立出来的最初目的,让前端的设计人员不得不过多的关注“程序”而非页面本身。要不然就得由程序员最终回头修改前端设计人员已经做好的模板文件。 更重要的一点时:如果在模板中引入太多的控制语句,那还不如直接在页面中写<?php ,因为PHP的本身就是模板引擎。无论哪种都快不过它。 所以,尽量将控制放在PHP程序体内,不要放到视图中去跑. 十一、LAMP架构下的加速系统 十二、各级加速系统说明 •WEB服务层 Nginx :自身支持反向代理,提供简单的负载均衡及从错机制,能很方便的搭建起web服务集群. Lighttpd:超轻量,合适搭建静态访问服务器 Squid:对动态内容亦能做缓存处理. •PHP层 APC:缓存opcode,减少了扫描和编译阶段,但仍无法实现持久对象.纯脚本效率提高在200%--500%,应用场景下实测通常能提高效率一倍. XCACHE •数据层 共享内存 Memcache: Key=>Value对形式的内存数据缓存服务.基于TCP连接.常用于缓存数据库查询结果.支持分布式. 缺点:关机即无,每次连接的时间开销大. 推荐的工具 •Editplus+PHP •XDEBUG+Eclipse PDT •SmartTemplate Xdebug+ WinCacheGrind 【本文首发于: 百度运维空间】 http://hi.baidu.com/ops_bd/blog/item/ae1a7b16c2a6b06acb80c4dd.html 【 关注百度技术沙龙】 本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/748346 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android内存优化11 内存泄漏常见情况2 线程持久化

线程持久化 Java中的Thread有一个特点就是她们都是直接被GC Root所引用,也就是说Dalvik虚拟机对所有被激活状态的线程都是持有强引用,导致GC永远都无法回收掉这些线程对象,除非线程被手动停止并置为null或者用户直接kill进程操作。所以当使用线程时,一定要考虑在Activity退出时,及时将线程也停止并释放掉 内存泄漏1:AsyncTask void startAsyncTask() { new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { while(true); } }.execute(); } super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View aicButton = findViewById(R.id.at_button); aicButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startAsyncTask(); nextActivity(); } }); 使用LeakCanary检测到的内存泄漏: 为什么? 上面代码在activity中创建了一个匿名类AsyncTask,匿名类和非静态内部类相同,会持有外部类对象,这里也就是activity,因此如果你在Activity里声明且实例化一个匿名的AsyncTask对象,则可能会发生内存泄漏,如果这个线程在Activity销毁后还一直在后台执行,那这个线程会继续持有这个Activity的引用从而不会被GC回收,直到线程执行完成。 怎么解决? 自定义静态AsyncTask类,并且让AsyncTask的周期和Activity周期保持一致,也就是在Activity生命周期结束时要将AsyncTask cancel掉。 内存泄漏2:Handler 非静态内部类导致的内存泄露在Android开发中有一种典型的场景就是使用Handler,很多开发者在使用Handler是这样写的: public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start(); } private void start() { Message msg = Message.obtain(); msg.what = 1; mHandler.sendMessageDelayed(msg,1000); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { // 做相应逻辑 } } }; } 也许有人会说,mHandler并未作为静态变量持有Activity引用,生命周期可能不会比Activity长,应该不一定会导致内存泄露呢,显然不是这样的! 熟悉Handler消息机制的都知道,mHandler会作为成员变量保存在发送的消息msg中,即msg持有mHandler的引用,而mHandler是Activity的非静态内部类实例,即mHandler持有Activity的引用,那么我们就可以理解为msg间接持有Activity的引用。msg被发送后先放到消息队列MessageQueue中,然后等待Looper的轮询处理(MessageQueue和Looper都是与线程相关联的,MessageQueue是Looper引用的成员变量,而Looper是保存在ThreadLocal中的)。那么当Activity退出后,msg可能仍然存在于消息对列MessageQueue中未处理或者正在处理,那么这样就会导致Activity无法被回收,以致发生Activity的内存泄露。 通常在Android开发中如果要使用内部类,但又要规避内存泄露,一般都会采用静态内部类+弱引用的方式。 public class MainActivity extends AppCompatActivity { private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHandler = new MyHandler(this); start(); } private void start() { Message msg = Message.obtain(); msg.what = 1; mHandler.sendMessage(msg); } private static class MyHandler extends Handler { private WeakReference<MainActivity> activityWeakReference; public MyHandler(MainActivity activity) { activityWeakReference = new WeakReference<>(activity); } @Override public void handleMessage(Message msg) { MainActivity activity = activityWeakReference.get(); if (activity != null) { if (msg.what == 1) { // 做相应逻辑 } } } } } mHandler通过弱引用的方式持有Activity,当GC执行垃圾回收时,遇到Activity就会回收并释放所占据的内存单元。这样就不会发生内存泄露了。 上面的做法确实避免了Activity导致的内存泄露,发送的msg不再已经没有持有Activity的引用了,但是msg还是有可能存在消息队列MessageQueue中,所以更好的是在Activity销毁时就将mHandler的回调和发送的消息给移除掉。 @Override protected void onDestroy() { super.onDestroy(); mHandler.removeCallbacksAndMessages(null); } 为什么? 创建的Handler对象为匿名类,匿名类默认持有外部类activity, Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。这时activity被handler持有 handler被message持有,message被messagequeue持有,message queue被loop持有,主线程的loop是全局存在的,这时就造成activity被临时性持久化,造成临时性内存泄漏 怎么解决? 可以由上面的结论看出,产生泄漏的根源在于匿名类持有Activity的引用,因此可以自定义Handler和Runnable类并声明成静态的内部类,来解除和Activity的引用。或者在activity 结束时,将发送的Message移除 内存泄漏3:Thread 代码如下:MainActivity.java void spawnThread() { new Thread() { @Override public void run() { while(true); } }.start(); } View tButton = findViewById(R.id.t_button); tButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { spawnThread(); nextActivity(); } }); 为什么?Java中的Thread有一个特点就是她们都是直接被GC Root所引用,也就是说Dalvik虚拟机对所有被激活状态的线程都是持有强引用,导致GC永远都无法回收掉这些线程对象,除非线程被手动停止并置为null或者用户直接kill进程操作。看到这相信你应该也是心中有答案了吧 : 我在每一个MainActivity中都创建了一个线程,此线程会持有MainActivity的引用,即使退出Activity当前线程因为是直接被GC Root引用所以不会被回收掉,导致MainActivity也无法被GC回收 怎么解决?当使用线程时,一定要考虑在Activity退出时,及时将线程也停止并释放掉 内存泄漏4:Timer Tasks Timer和TimerTask在Android中通常会被用来做一些计时或循环任务,比如实现无限轮播的ViewPager: public class MainActivity extends AppCompatActivity { private ViewPager mViewPager; private PagerAdapter mAdapter; private Timer mTimer; private TimerTask mTimerTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); mTimer.schedule(mTimerTask, 3000, 3000); } private void init() { mViewPager = (ViewPager) findViewById(R.id.view_pager); mAdapter = new ViewPagerAdapter(); mViewPager.setAdapter(mAdapter); mTimer = new Timer(); mTimerTask = new TimerTask() { @Override public void run() { MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { loopViewpager(); } }); } }; } private void loopViewpager() { if (mAdapter.getCount() > 0) { int curPos = mViewPager.getCurrentItem(); curPos = (++curPos) % mAdapter.getCount(); mViewPager.setCurrentItem(curPos); } } private void stopLoopViewPager() { if (mTimer != null) { mTimer.cancel(); mTimer.purge(); mTimer = null; } if (mTimerTask != null) { mTimerTask.cancel(); mTimerTask = null; } } @Override protected void onDestroy() { super.onDestroy(); stopLoopViewPager(); } } 当我们Activity销毁的时,有可能Timer还在继续等待执行TimerTask,它持有Activity的引用不能被回收,因此当我们Activity销毁的时候要立即cancel掉Timer和TimerTask,以避免发生内存泄漏。 为什么? 这里内存泄漏在于Timer和TimerTask没有进行Cancel,从而导致Timer和TimerTask一直引用外部类Activity。 怎么解决? 在适当的时机进行Cancel。 内存泄漏5:属性动画造成内存泄露 动画同样是一个耗时任务,比如在Activity中启动了属性动画(ObjectAnimator),但是在销毁的时候,没有调用cancle方法,虽然我们看不到动画了,但是这个动画依然会不断地播放下去,动画引用所在的控件,所在的控件引用Activity,这就造成Activity无法正常释放。因此同样要在Activity销毁的时候cancel掉属性动画,避免发生内存泄漏。 @Override protected void onDestroy() { super.onDestroy(); mAnimator.cancel(); } 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/8473376.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

LAMP架构下的Web开发概念、流程及优化策略(一)

架构设计——前端架构•后端架构•视觉体系对接约定——接口约定•标识约定•通讯代码约定开发——建立开发框架•建立数据库•实施编码测试——功能测试•性能测试 一、架构设计 二、对接约定 1、接口约定 约定请求方式(普通HTTP请求,XMLHTTP请求,SOAP请求,phprpc请求)、请求类型(POST,GET,HEADER)、请求地址、请求参数。(前端请求四要素,文档中体现,程序中实现。) 2、标识约定 为确保前后端并行开发,减少开发的时间周期,需要在开发前就做好标识约定,通过文档描述清楚前端模板变量和后端程序变量之间的约定关系,以及后端返回各种状态值的含义。 建议的最佳应用是:后端不对用户视图负责,只管输出状态代码。呈现给用户的视图由前端负责。 三、各类web服务器优缺点比较 •Nginx 优点:原生支持反向代理,带有简单的负载均衡及容错机制。速度最快。(10%-1000%),占用资源很少。 缺点:文档较少,手工配置,只能以fast-cgi方式运行php. •Apache 优点:文档丰富,稳定(!?),应用环境多。 缺点:占用资源较多,高压力下表现性能不如nginx或lighttpd,手工配置。 •IIS 优点:文档丰富,win平台下安装简单配置方便 缺点:不支持跨平台,性能低下。 四、常见web系统组织图 五、PHP在web应用中的特点 •语言弱类型 •脚本运行,生命周期短。 •面向对象与面向过程并存。 •弱效率、重流程、强扩展。 1、PHP的优点 •适合web开发。将web开发中常用的行为、内容做了良好的封装。程序员可以很轻易的使用它们。 •基于脚本的运行方式,修改代码后不需要重新编译,很多情况下也不需要重启服务器。 •开发快捷,部署方便,支持环境众多。 •非常优秀的扩展能力。非常多的扩展子件。 •开发框架众多。对多种数据库支持很好 •良好的社区支持,本身开源。修改容易 2、PHP的缺点 •容易写出坏的代码。(解决方法:严格遵循规范) •效能不高。(解决方法:复杂业务使用C扩展) •每次执行都要经历扫描-编译-执行的阶段,无执久对象模型。(解决方法:使用APC) •命名混乱,参数混乱,得随时翻着手册 3、PHP框架 •对开发者起编码约束作用。 •提供了ORM,使对数据库变成对数据对象的访问,让程序员对数据的处理更加专注于面向对象上. •通过配置(无需改动代码)即能变更服务环境,使得迁移成本减小 •方便程序员实现完整的MVC开发模式.使程序员更专注于业务领域,不再过多关注建立数据模型的底层代码以及处理视图展示. •内置大量开发中的常用工具。可随时调用。也可自己扩展编写。 •本身即由PHP编写。可随时修改以满足达到自己的需求。 【本文首发于: 百度运维空间】 http://hi.baidu.com/ops_bd/blog/item/c2e2f94986ad95ded0c86ad2.html 【 关注百度技术沙龙】 本文转自百度技术51CTO博客,原文链接:http://blog.51cto.com/baidutech/748354 ,如需转载请自行联系原作者

优秀的个人博客,低调大师

.net执行性能,Winform性能优化?如何提高.net程序性能

2003年开始由vb/vc转向.net(C#)开发,.net的开发效率确实非常的高,我们主要作C/S的业务处理程序,对程序的响应速度要求比较高,用户不希望在界面上等待。在这方面,.net作的太烂了,根据无法跟vb之类编译成本机代码的程序性能相比,我想园子中搞winform开发的有好很多人吧,不知你们是怎样处理这个问题的,大家是如何忧化.net代码的。 求dudu放在首页一天,也希望园子的朋友们讨论这个问题 谢谢大家,我增加几个相关的连接? 微软对.NET失去信心?.NET专家激起千层浪 http://www.yesky.com/113/1924613.shtml 托管代码和非托管代码效率的对比。 http://www.cnblogs.com/wuchang/archive/2006/12/07/584997.html 作者:魏琼东出处:http://www.cnblogs.com/eastjade关于作者:有13年的软件从业经历,专注于中小软件企业软件开发过程研究,通过在技术与管理帮助中小软件企业实现技术层面开源节流的目的。熟悉需求分析、企业架构、项目管理。现主要从事基于AgileEAS.NET平台的技术咨询工作,主要服务于医疗卫生、铁路、电信、物流、物联网、制造、零售等行业。如有问题或建议,请多多赐教!本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过mail.james@qq.com联系我,也可以加入QQ群:113723486、199463175、116773358、116773358、212867943、147168308、59827496、193486983、15118502和大家共同讨论,非常感谢。 本文转自魏琼东博客园博客,原文链接:http://www.cnblogs.com/eastjade/archive/2007/06/13/782569.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android内存优化10 内存泄漏常见情况1 静态持久化

1,内存泄漏到本质是该释放的对象被持久化的对象引用了,造成持久化的常见情况有1,静态持久化 2,线程持久化 线程持久化 因为存活的线程是有dvk虚拟久直接持有,所以存活的线程都是持久化的 内存泄漏1:静态Activities(static Activities) 代码如下:MainActivity.Java public class MainActivity extends AppCompatActivity { private static MainActivity activity; TextView saButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); saButton = (TextView) findViewById(R.id.text); saButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setStaticActivity(); nextActivity(); } }); } void setStaticActivity() { activity = this; } void nextActivity(){ startActivity(new Intent(this,RegisterActivity.class)); SystemClock.sleep(1000); finish(); } @Override protected void onDestroy() { super.onDestroy(); //使用LeakCanary观察是否有内存泄漏 MyApplication.getRefWatcher().watch(this); } } LeakCanary检测出的内存泄漏: 为什么? 在上面代码中,我们声明了一个静态的Activity变量并且在TextView的OnClick事件里引用了当前正在运行的Activity实例,所以如果在activity的生命周期结束之前没有清除这个引用,则会引起内存泄漏。因为声明的activity是静态的,会常驻内存,如果该对象不清除,则垃圾回收器无法回收变量。 怎么解决? 最简单的方法是在onDestory方法中将静态变量activity置空,这样垃圾回收器就可以将静态变量回收。 @Override protected void onDestroy() { super.onDestroy(); activity = null; //使用LeakCanary观察是否有内存泄漏 MyApplication.getRefWatcher().watch(this); } 不使用静态activity,或给静态activity赋值时,考虑赋值的activity生命周期是不是全局的,或者在静态activity使用完后及时释放 内存泄漏2:静态View 代码如下:MainActivity.java ... private static View view; TextView saButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); saButton = (TextView) findViewById(R.id.text); saButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setStaticView(); nextActivity(); } }); } void setStaticView() { view = findViewById(R.id.sv_view); } ... LeakCanary检测到的内存泄漏 为什么? 上面代码看似没有问题,在Activity里声明一个静态变量view,然后初始化,当Activity生命周期结束了内存也释放了,但是LeakCanary却显示出现了内存泄漏,为什么?问题出在这里,View一旦被加载到界面中将会持有一个Context对象的引用,在这个例子中,这个context对象是我们的Activity,声明一个静态变量引用这个View,也就引用了activity,所以当activity生命周期结束了,静态View没有清除掉,还持有activity的引用,因此内存泄漏了。 怎么解决? 在onDestroy方法里将静态变量置空。 @Override protected void onDestroy() { super.onDestroy(); view = null; MyApplication.getRefWatcher().watch(this); } 不使用静态view,或在activity关闭时将静态view赋值为null 内存泄漏3:静态内部类 代码如下:MainActivity.java private static Object inner; void createInnerClass() { class InnerClass { } inner = new InnerClass(); } View icButton = findViewById(R.id.ic_button); icButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { createInnerClass(); nextActivity(); } }); 使用LeakCanary检测到的内存泄漏: 为什么? 非静态内部类会持有外部类的引用,在上面代码中内部类持有Activity的引用,因此inner会一直持有Activity,如果Activity生命周期结束没有清除这个引用,这样就发生了内存泄漏。 怎么解决? 因为非静态内部类隐式持有外部类的强引用,所以我们将内部类声明成静态的就可以了。 void createInnerClass() { static class InnerClass { } inner = new InnerClass(); } 内存泄漏3:静态Drawable 当一个Drawable附加到一个 View上时, View会将其作为一个callback设定到Drawable上。意味着Drawable拥有一个View的引用,上面说了view会有上下文的引用 内存泄漏4:静态集合中对象没清理造成的内存泄漏 我们通常把一些对象的引用加入到了集合中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大。如果这个集合是static的话,那情况就更严重了。 内存泄漏5:单例导致内存泄露 单例模式在Android开发中会经常用到,但是如果使用不当就会导致内存泄露。因为单例的静态特性使得它的生命周期同应用的生命周期一样长,如果一个对象已经没有用处了,但是单例还持有它的引用,那么在整个应用程序的生命周期它都不能正常被回收,从而导致内存泄露。 public class AppSettings { private static AppSettings sInstance; private Context mContext; private AppSettings(Context context) { this.mContext = context; } public static AppSettings getInstance(Context context) { if (sInstance == null) { sInstance = new AppSettings(context); } return sInstance; } } 像上面代码中这样的单例,如果我们在调用getInstance(Context context)方法的时候传入的context参数是Activity、Service等上下文,就会导致内存泄露。 以Activity为例,当我们启动一个Activity,并调用getInstance(Context context)方法去获取AppSettings的单例,传入Activity.this作为context,这样AppSettings类的单例sInstance就持有了Activity的引用,当我们退出Activity时,该Activity就没有用了,但是因为sIntance作为静态单例(在应用程序的整个生命周期中存在)会继续持有这个Activity的引用,导致这个Activity对象无法被回收释放,这就造成了内存泄露。 为了避免这样单例导致内存泄露,我们可以将context参数改为全局的上下文: private AppSettings(Context context) { this.mContext = context.getApplicationContext(); } 全局的上下文Application Context就是应用程序的上下文,和单例的生命周期一样长,这样就避免了内存泄漏。 单例模式对应应用程序的生命周期,所以我们在构造单例的时候尽量避免使用Activity的上下文,而是使用Application的上下文。 本文转自 一点点征服 博客园博客,原文链接:http://www.cnblogs.com/ldq2016/p/8472913.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android内存优化12 内存泄漏常见情况3 注册持久化

android 中有很多注册和反注册,由于在注册后,上下文自身会被持久化的观察者列表所持有,如果不进行反注册,就会造成内存泄漏 内存泄漏1:Sensor Manager 代码如下:MainActivity.java void registerListener() { SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL); sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST); } View smButton = findViewById(R.id.sm_button); smButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { registerListener(); nextActivity(); } }); 为什么? 通过Context调用getSystemService获取系统服务,这些服务运行在他们自己的进程执行一系列后台工作或者提供和硬件交互的接口,如果Context对象需要在一个Service内部事件发生时随时收到通知,则需要把自己作为一个监听器注册进去,这样服务就会持有一个Activity,如果开发者忘记了在Activity被销毁前注销这个监听器,这样就导致内存泄漏。 怎么解决? 在onDestroy方法里注销监听器。 内存泄漏1:未取消注册或回调导致内存泄露 比如我们在Activity中注册广播,如果在Activity销毁后不取消注册,那么这个刚播会一直存在系统中,同上面所说的非静态内部类一样持有Activity引用,导致内存泄露。因此注册广播后在Activity销毁后一定要取消注册。 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.registerReceiver(mReceiver, new IntentFilter()); } private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 接收到广播需要做的逻辑 } }; @Override protected void onDestroy() { super.onDestroy(); this.unregisterReceiver(mReceiver); } } 在注册观察则模式的时候,如果不及时取消也会造成内存泄露。比如使用Retrofit+RxJava注册网络请求的观察者回调,同样作为匿名内部类持有外部引用,所以需要记得在不用或者销毁的时候取消注册。 WebView造成内存泄露 关于WebView的内存泄露,因为WebView在加载网页后会长期占用内存而不能被释放,因此我们在Activity销毁后要调用它的destory()方法来销毁它以释放内存。 另外在查阅WebView内存泄露相关资料时看到这种情况: Webview下面的Callback持有Activity引用,造成Webview内存无法释放,即使是调用了Webview.destory()等方法都无法解决问题(Android5.1之后)。 最终的解决方案是:在销毁WebView之前需要先将WebView从父容器中移除,然后在销毁WebView。详细分析过程请参考这篇文章:WebView内存泄漏解决方法。 @Override protected void onDestroy() { super.onDestroy(); // 先从父控件中移除WebView mWebViewContainer.removeView(mWebView); mWebView.stopLoading(); mWebView.getSettings().setJavaScriptEnabled(false); mWebView.clearHistory(); mWebView.removeAllViews(); mWebView.destroy(); } 本文转自 一点点征服 博客园博客,原文链接: http://www.cnblogs.com/ldq2016/p/8473439.html ,如需转载请自行联系原作者

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

用户登录
用户注册