I am using RxJava's Observable.zip method to combine two API calls into one result. For some reason I am getting a memory leak despite the fact that I unsubscribe from the subscription. I am not sure if this a bug on my end or if there is something I need to do with the creation of the Observable.
protected void onCreate(Bundle bundle) {
...
subscription = Observable.zip(
api.getConfiguration(),
api.getSettings().map(r -> r.getData()),
new Func2<ConfigurationResponse, List<Datum>, Struct>() {
#Override
public Struct call(ConfigurationResponse config, List<Datum> data) {
return new Struct(data, config.getCopy(), config.getSettings());
}
}
)
.compose(Schedulers.applyApiSchedulers())
.subscribe(
struct -> {
configurationManager.set(struct.data, struct.copy, struct.settings);
startNextActivity();
},
error -> {
startNextActivity();
}
);
}
protected void onDestroy() {
if (!subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
Here is the trace from Leak Canary.
Any help would be appreciated.
I suspect the leak comes from the subscription itself as you seem to keep referencing the Subscriber through it. Try clearing that reference in onDestroy and check again for leaks.
This is probably a leak in retrofit, a similar one seems to have been reported here.
Note that if retrofit leaks the subscriber, you may be able to limit the impact if your mapper func no longer references your activity instance.
In your case Struct is probably a non-static instance class (hence having an implicit reference to the activity instance), if you manage to make it static w/o referencing the activity, you'll likely get rid of this very leak.
Related
I'm still a bit confused about memory leaks in Android handlers. Android Studio seems to warn about possible memory leaks with any non-static handler, but all the examples use postDelayed() either explicitly or implicitly.
I have code that looks like this
public class MyActivity extends Activity {
public boolean handlerIsDone = false;
private MyHandler handler = new Myhandler(getContentResolver());
private class MyHandler extends AsyncQueryhandler {
public QueryHandler(ContentResolver cr) { super(cr); }
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
...
mActivity.handlerIsDone = true;
}
}
protected void onCreate(Bundle icicle) {
Activity mActivity = this;
handler.startQuery(...);
}
...
}
I haven't checked that this compiles, it's just to show the structure. In the real app, both Activity and MyHandler do other stuff. When the activity is destroyed, both it and handler still hold references to each other, but there is no reference to handler in the message queue, or anywhere else outside the activity. Is the Android garbage collector smart enough to free the memory of both of them?
If so, why doesn't Android Studio warn just on uses of postDelayed(), rather than on every non-static handler declaration? This type of handler usage is a very common Android paradigm to get some slow-running code out of the UI thread, and it isn't very helpful to get a warning when there is actually nothing wrong with it.
Having an huge customers profile page if two or more users start using same page and start editing big change will happen in my database so planing to implement Threads concept where only one user can use that customer page
i'm aware about threads concept but confused how to implement it
hope i need to use Singleton class as well
Any suggestion or Logic's will be helpful
I'm using Struts,Hibernate frame work
You may use application context to store a flag variable. Action will use its value to allow only one simultaneous execution.
public class TestAction extends ActionSupport implements ApplicationAware {
private static final String APP_BUSY_KEY = "APP_BUSY";
Map<String, Object> map;
#Override
public void setApplication(Map<String, Object> map) {
this.map = map;
}
#Override
public String execute() throws Exception {
if (map.containsKey(APP_BUSY_KEY)) {
return ERROR;
} else {
map.put(APP_BUSY_KEY, "1");
try {
// action logic here
} finally {
map.remove(APP_BUSY_KEY);
}
return SUCCESS;
}
}
}
If you plan to implement similar logic for two requests (lock after displaying values and release lock after submitting new values) then logic will be more complex and you will also need to handle lock release after timeout.
I've seen so many questions similar to mine, but no answers that quite seem to apply to my situation.
My ASP.NET MVC app with EF 6 Code first and Unity has a web service that adds something to the database, then fires off another thread that adds more stuff to the database. The reason for using the other thread is to return the original request as quickly as possible. The context class is obtained using the Unity container RegisterType().
I've got lots of repository classes all using the same context, so to make sure they get the same instance I could use the PerRequestLifetimeManager in my Unity container, and that's fine for the http request threads but that the other threads can't use the context returned by the PerRequestLifetimeManager because this is only valid on the original http request thread.
So, I can use the PerThreadLifetimeManager. This is great because now the main request thread and the other thread it kicks off get the same instance of the context returned by Unity. The trouble is that so do other requests if they get given the same thread, so this is no good either.
So how can I configure things so that the request threads get their own PerRequest Lifetime Manager created context, and other threads get a different context?
The issue is made a little more difficult by the fact that the new thread calls other classes that need to use a context instance. However, these other classes can be used from the main request thread or the new thread, so grabbing a context instance when the thread is started and then passing it around will be tricky.
Thanks in advance
No takers then...
I'm going to have a go at answering my own question, but could do with some thoughts on my approach.
So I can't use the PerRequestLifetimeManager because worker threads can't use the context that this returns, but I can't use the PerThreadLifetimeManager because the context can last the lifetime of several HTTP requests. This class attempts to provide the best of both worlds.
/// <summary>
/// For the context class the PerRequestLifetimeManager is the most suitable lifetime manager,
/// but this doesn't work when a new worker thread is started as this needs to access the context.
/// The PerThreadLifetimeManager is no good either as the context can last for more than on request.
/// This class attempts to give the best of both worlds: per request lifetime management for HTTP requests
/// and thread storage for worker threads.
/// </summary>
public class PerRequestOrThreadLifetimeManager : PerRequestLifetimeManager, IDisposable
{
private const string threadDataSlotName = "PerRequestOrThreadLifetimeManager";
public override object GetValue()
{
if (System.Web.HttpContext.Current != null)
{
return base.GetValue();
}
else
{
return getManagedObject();
}
}
public override void RemoveValue()
{
throw new NotImplementedException();
}
public override void SetValue(object newValue)
{
if (System.Web.HttpContext.Current != null)
{
base.SetValue(newValue);
}
else
{
Thread.SetData(Thread.GetNamedDataSlot(threadDataSlotName), newValue);
}
}
private object getManagedObject()
{
return Thread.GetData(Thread.GetNamedDataSlot(threadDataSlotName));
}
public void Dispose()
{
try
{
IDisposable obj = getManagedObject() as IDisposable;
if (obj != null)
{
obj.Dispose();
obj = null;
}
}
catch { }
}
}
I have a custom calendar control for which there is an custom viewbinding. In this viewbinding we hook up some events which are not decoupled correct and therefor is the garbage collecting not completed. In the following is our custom view binding. As you can see the event is hooked up in the constructor and decoupled in the OnSelectedDate event is triggered(the user selects an date). Therefore if you choose a date the event is decouple correct and garbage collected but if you just go back, the event is still hooked up and no garbage collecting is performed. I thought about trigger the event with null values and and thereby decoulpe the event. But I think there must be some more clever way to achieve this.
namespace CmsApp.Core.Binders
{
public class CalendarViewBinding:MvxBaseTargetBinding
{
private CalendarView _calendarView;
private DateTime _currentValue;
public CalendarViewBinding(CalendarView calendarView)
{
_calendarView = calendarView;
_calendarView.OnDateSelected+=OnDateSelected;
}
protected override void Dispose(bool isDisposing)
{
if(_calendarView!=null)
{
_calendarView.OnDateSelected -= OnDateSelected;
_calendarView = null;
}
base.Dispose(isDisposing);
}
private void OnDateSelected(object sender, SelectedDateEventArgs args)
{
_currentValue = args.SelectedDate;
this.FireValueChanged(_currentValue);
_calendarView.OnDateSelected -= OnDateSelected;
}
public override void SetValue(object value)
{
var date = (DateTime)value;
_currentValue = date;
_calendarView.SelectedDate = _currentValue;
}
public override Type TargetType
{
get
{
return typeof(DateTime);
}
}
public override MvxBindingMode DefaultMode
{
get
{
return MvxBindingMode.TwoWay;
}
}
}
}
Any help is appreciated :)
It looks to me like your binding is almost correct.
The only issue I can see is that it unsubscribes from the event too often - you can't call _calendarView.OnDateSelected -= OnDateSelected; twice - but I don't think this is the problem you are seeing.
I currently would guess that the problem is not in the code you are using:
either there's a bug in the binding code in the underlying framework you are using
or something is a bug/issue in the way you are using this binding
or your memory leak has nothing to do with this binding
It's not easy to test this from the limited code posted here, but it would be simpler if you could produce a simple app that reproduces the leak you are seeing. Share that and you might be able to get more feedback.
If you believe my guesses are wrong, then the only thing I can suggest is that you switch to WeakReferences inside your binding - but this feels like a sticking plaster rather than a cure.
Just adding a link to when to release objects in mono touch / mvvmcross
First thing: This is a compact framework 3.5 application.
I have a very weird problem. In a Dispose-Method the application disposes items in a collection and after that clears the list. So far nothing special and it works like a charm when Dispose is called by my application. But as soon as the Garbage Collector calls the Finalizer, which calls the same Dispose-Method the system throws a NotSupported-Exception on the Clear-Method of the generic collection.
Here is the body of the Dispose-Method:
public override void Dispose()
{
if (items != null)
{
foreach (Shape item in items)
{
item.Dispose();
}
items.Clear();
items = null;
}
base.Dispose();
}
I'm totally stuck here. Maybe someone can explain this to me, or had a similar problem and solved it.
A finalizer needs only call Dispose if there are unmanaged resources to clean up. You cannot attempt to access managed resources when being called from the finalizer.
As mentioned in the comment above, there is no reason [that we can see] that your class should implement a finalizer.
For reference, should you need to use a finalizer, the Dispose pattern to use as follows:
// The finalizer
~MyClass()
{
Dispose(false);
}
// The IDisposable implemenation
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// The "real" dispose method
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Dispose managed objects here
}
else
{
// Free unmanaged resources here
}
_disposed = true;
}
}