A story that people who did iOS solidly may be addicted to the implementation of Listener when moving to Android

at first

After implementing iOS for a while, if you start implementing Android after a long time, For some reason, I was a little annoyed that the Listener instance was released at a strange timing.

What i did

Perhaps everyone has written once, Delegate on iOS, Listener on Android ↓ I implemented it like this. I don't care about the method name or the wrong style this time.

iOS


import UIKit

// UI
class ViewController: UIViewController, ModelDelegate {
    
    let model = Model()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        model.delegate = self
    }
    
    func notify(model: Model) {
    }
}

//Model and protocol for notifications
protocol ModelDelegate: class {
    func notify(model: Model)
}
class Model {
    weak var delegate: ModelDelegate?
    
    func doSomething() {
        //Do something
        delegate?.notify(model: self)
    }
}

Android


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.lang.ref.WeakReference;

// UI
public class MainFragment extends Fragment {

    private Model model;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        this.model = new Model();
        model.setListener(new ModelListener() {
            @Override
            public void notify(Model model) {

            }
        });

        return super.onCreateView(inflater, container, savedInstanceState);
    }
}

//Model and interface for notifications
interface ModelListener {
    void notify(Model model);
}

class Model {

    private WeakReference<ModelListener> mListener;

    void setListener(ModelListener listener) {
        mListener = new WeakReference<>(listener);
    }

    void doSomething() {
        //Do something
        //Actually check null

        mListener.get().notify(this);
    }
}

So, this works fine on iOS. It seems to work fine on Android, but at one point mListener.get () suddenly returns null.

Cause

It was said that if implemented with an anonymous class, there is no instance that strongly references Listener, so it will be the target of GC. mListener.get () will return null when the GC runs.

It was okay because it was strongly referenced when implemented in a normal class, not an anonymous class.

Thoughts

(Then shouldn't it be a Weak Reference? But if you make a strong reference, it will circulate when you implement it in a normal class that is not an anonymous class. Eh, is java a fucking language that forces you to implement an interface?)

I thought, but of course that wasn't the case, and I was the one who was shit.

After all

As you may have noticed, java has a GC, so there is no problem even if it circulates. So I changed it to a normal reference instead of a Weak Reference.

People who have only done iOS should be careful when writing a language with GC.

At the end

It was a good experience to realize that anonymous classes are a possible concept because of GC.

Recommended Posts

A story that people who did iOS solidly may be addicted to the implementation of Listener when moving to Android
The story of introducing Gradle as a retrofit to an existing system that did not manage packages
A memo that was soberly addicted to the request of multipart / form-data
A story I was addicted to when testing the API using MockMVC
A story confirming the implementation of the SendGrid Java library when mail delivery fails
A story addicted to EntityNotFoundException of getOne of JpaRepository
The story that did not disappear when I tried to delete mysql on ubuntu
A memorandum because I was addicted to the setting of the Android project of IntelliJ IDEA
A story that did not work when trying to handle events in Notification Center
A story I was addicted to when getting a key that was automatically tried on MyBatis
Convert an array that may be null to a stream
The story I was addicted to when setting up STS
A collection of patterns that you want to be aware of so as not to complicate the code
Let's try the implementation to find the area of the triangle that we did in the training for newcomers
The story of making a binding for libui, a GUI library for Ruby that is easy to install
A story that made me regret when a "NotReadablePropertyException" occurred during the development of the Spring Boot application.
[Rails] A story that continued to incorrectly verify the reason why the update action did not pass (update)
When you want to check whether the contents of a property can be converted to a specific type
A story that could be implemented neatly by using polymorphism when you want to express two types of data in one table