Android 调用改装2时避免内存泄漏
通过下面的文章,我发现在onCreate()方法上调用Reformation enqueue()可能会导致内存泄漏 这篇文章是这样说的: 在主线程中调用改装Android 调用改装2时避免内存泄漏,android,memory-leaks,retrofit,retrofit2,Android,Memory Leaks,Retrofit,Retrofit2,通过下面的文章,我发现在onCreate()方法上调用Reformation enqueue()可能会导致内存泄漏 这篇文章是这样说的: 在主线程中调用改装 public class MoviesActivity extends Activity { private TextView mNoOfMoviesThisWeek; @Override protected void onCreate(Bundle savedInstanceState) { s
public class MoviesActivity extends Activity {
private TextView mNoOfMoviesThisWeek;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_movies_activity);
mNoOfMoviesThisWeek = (TextView) findViewById(R.id.no_of_movies_text_view);
MoviesRepository repository = ((MoviesApp) getApplication()).getRepository();
repository.getMoviesThisWeek()
.enqueue(new Callback<List<Movie>>() {
@Override
public void onResponse(Call<List<Movie>> call,
Response<List<Movie>> response) {
int numberOfMovies = response.body().size();
mNoOfMoviesThisWeek.setText("No of movies this week: " + String.valueOf(numberOfMovies));
}
@Override
public void onFailure(Call<List<Movie>> call, Throwable t) {
// Oops.
}
});
}
}
private static class RetrofitCall extends AsyncTask<Void, Void, List<Show>> {
private WeakReference<TextView> numberOfShows;
public RetrofitCall(TextView numberOfShows) {
this.numberOfShows = new WeakReference<>(numberOfShows);
}
@Override
protected List<Show> doInBackground(Void... voids) {
List<Show> showList = new ArrayList<>();
if (!isCancelled()) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(TvMazeService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
TvMazeService service = retrofit.create(TvMazeService.class);
try {
Response<List<Show>> response = service.getShows().execute();
if (response.isSuccessful()) {
showList = response.body();
}
return showList;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(List<Show> shows) {
super.onPostExecute(shows);
TextView textView = numberOfShows.get();
if (textView != null) {
String number = String.valueOf(shows.size());
textView.setText(number);
}
}
}
公共类电影活动扩展活动{
私人文本视图mnoofmoviesthisbeek;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.layout\u活动);
mNoOfMoviesThisWeek=(TextView)findViewById(R.id.no_of_movies_text_view);
MoviesRepository repository=((MoviesApp)getApplication()).getRepository();
repository.getMoviesThisWeek()
.enqueue(新的回调函数(){
@凌驾
公共void onResponse(调用,
回应(回应){
int numberOfMovies=response.body().size();
mNoOfMoviesThisWeek.setText(“本周电影数量:”+String.valueOf(numberOfMovies));
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
//哎呀。
}
});
}
}
现在,如果此网络调用在非常慢的连接上运行,并且在调用结束之前,活动以某种方式被旋转或破坏,那么整个活动实例将泄漏
我试着在我的应用程序上做同样的事情。我在onCreate()方法中使用ign enqueue()调用了一个大内容(240个对象)。然后,在加载内容时,我将设备旋转了多次,并向我展示了文章中所说的活动中的内存泄漏
然后我尝试了两种方法来避免内存泄漏:
第一选项
使用静态内部类在后台线程上调用reformation execute()方法
在后台线程中调用改装
public class MoviesActivity extends Activity {
private TextView mNoOfMoviesThisWeek;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_movies_activity);
mNoOfMoviesThisWeek = (TextView) findViewById(R.id.no_of_movies_text_view);
MoviesRepository repository = ((MoviesApp) getApplication()).getRepository();
repository.getMoviesThisWeek()
.enqueue(new Callback<List<Movie>>() {
@Override
public void onResponse(Call<List<Movie>> call,
Response<List<Movie>> response) {
int numberOfMovies = response.body().size();
mNoOfMoviesThisWeek.setText("No of movies this week: " + String.valueOf(numberOfMovies));
}
@Override
public void onFailure(Call<List<Movie>> call, Throwable t) {
// Oops.
}
});
}
}
private static class RetrofitCall extends AsyncTask<Void, Void, List<Show>> {
private WeakReference<TextView> numberOfShows;
public RetrofitCall(TextView numberOfShows) {
this.numberOfShows = new WeakReference<>(numberOfShows);
}
@Override
protected List<Show> doInBackground(Void... voids) {
List<Show> showList = new ArrayList<>();
if (!isCancelled()) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(TvMazeService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
TvMazeService service = retrofit.create(TvMazeService.class);
try {
Response<List<Show>> response = service.getShows().execute();
if (response.isSuccessful()) {
showList = response.body();
}
return showList;
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
protected void onPostExecute(List<Show> shows) {
super.onPostExecute(shows);
TextView textView = numberOfShows.get();
if (textView != null) {
String number = String.valueOf(shows.size());
textView.setText(number);
}
}
}
私有静态类调用扩展了异步任务{
私人WeakReference numberOfShows;
公用电话(TextView numberOfShows){
this.numberOfShows=新的WeakReference(numberOfShows);
}
@凌驾
受保护列表背景(无效…无效){
List showList=new ArrayList();
如果(!isCancelled()){
改装改装=新改装.Builder()
.baseUrl(TvMazeService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
TvMazeService服务=改装.create(TvMazeService.class);
试一试{
响应=service.getShows().execute();
if(response.issusccessful()){
showList=response.body();
}
退货清单;
}捕获(IOE异常){
e、 printStackTrace();
}
}
返回null;
}
@凌驾
受保护的void onPostExecute(列表显示){
super.onPostExecute(显示);
TextView TextView=numberOfShows.get();
if(textView!=null){
String number=String.valueOf(shows.size());
textView.setText(数字);
}
}
}
然后,我再次尝试使用LeakCanary获取内存泄漏,碰巧内存泄漏消失了
第二选项
使用
正如您在文档中所看到的,在ViewModel类中使用ViewModel时,我称之为“异步改造”,当屏幕旋转(活动被破坏)时,不需要再次加载数据,因为数据仍然保存
这种方法也不会导致内存泄漏,在讨论内存时是最好的方法
问题
1) 那么,使用ViewModel调用翻新是最好的选择,它真的可以避免内存泄漏吗
2) 像MoviesActivity那样,在onCreate()中使用enqueue()调用Reformation有什么问题吗
3) 在这种方法中,哪种方法最适合调用以验证用户身份?1)以正确的方式使用ViewModel不会导致内存泄漏,是一个不错的选择。你可以看到,还有这堂课,讲的是。第二节课对这个话题做了很好的解释
2) 在onCreate()中调用Reformation enqueue()是一个问题,它会导致内存泄漏。问题在于,当您第一次启动称为改装的活动时,当您旋转设备时,所有活动都会被销毁并重新创建。如果在数据加载完成之前旋转设备,则在再次调用onCreate()时将第二次调用Reformation,如果继续执行10次,将调用Reformation 10次,然后停止旋转设备。调用的结果将开始出现,bzzz:(结果将显示10次,因为您调用了10次。这意味着存在巨大的内存泄漏。如果您实施此方法并使用,您将看到泄漏
3) 最好的方法是什么
- 在onCreate()中使用enqueue()方法肯定不好李>
- 静态内部类(使用AsyncTask)是好的,但它不能在配置更改后继续存在,因为您需要在onDestroy()中取消它。这就是为什么它不会导致内存泄漏,因为任务已在onDestroy()中取消
- MVP是一种非常好的进行改装呼叫的方法。您可以从中了解更多信息,源代码如下李>
- 阅读本文中MVP和MVVM之间的区别
- 最后,谷歌建议开发者在这些场景中使用