繁体   English   中英

包含可运行的方法的返回类型

[英]return type for method with runnable in it

我正在使用执行程序进行后台操作。 我有一个方法可以从房间数据库中获取数据并返回一个字符串,以便我可以将它从存储库发送到视图模型中。

当方法中有一个可运行时,如何在方法中返回一个字符串? 请参阅以下代码以获得更好的描述:

 public String singleLoad(final int id){
    DefaultExecutorSupplier.getInstance().forBackgroundTasks()
            .execute(new Runnable() {
                @Override
                public void run() {
                    favNewsDao.loadSingle(id);
                }
            });
    return favNewsDao.loadSingle(id);

}

返回给出异常,说不能访问主线程上的数据库。 我怎样才能从这个方法中获取一个字符串,就像我在这个 ViewModel 类中一样

public String singleLoad(int id) {
    return repository.singleLoad(id);
}

您可以使用 ExecutorService 并提交 Callable,而不是使用 Executor。 更多信息: https : //developer.android.com/reference/java/util/concurrent/ExecutorService.html#submit(java.util.concurrent.Callable%3CT%3E)

第一种方法

在 Repository 类中,使用计数值为 1 的CountDownLatch ,直到它达到 0 以返回正确的结果,这可以通过使用此CountDownLatch await()来实现,它允许敦促执行底层代码直到闩锁计数值达到 0。

CountDownLatch mLatch;
String singleLoad;

public String singleLoad(final int id){

    mLatch = new CountDownLatch(1); // latch count is 1

    DefaultExecutorSupplier.getInstance().forBackgroundTasks()
            .execute(new Runnable() {
                @Override
                public void run() {
                    singleLoad = favNewsDao.loadSingle(id);
                    mLatch.countDown(); // Now you can allow returning back the result (id)
                }
            });

    // Don't return now and wait until the Executer is done
    try {
        // Application's main thread awaits, till the 
        // CountDownLatch count value reaches 0
        mLatch.await(); 

    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return mId;

}

更新

由于第一种方法可能存在内存泄漏,这里是第二种方法,使用侦听器而不是CountDownLatch

第二种方法

每当需要的字符串从 Room 数据库返回到 Repository 类时,我都会触发一个监听器; 侦听器在活动中注册,级联到 ViewModel,然后到 Repository。 侦听器有一个回调函数,它从数据库中检索返回的字符串,最终返回给活动。

道接口

@Dao
public interface MyDao {
    ...
    @Query("SELECT text FROM notes WHERE id = :id") // change types according to your database
    String loadSingle(int id);
}

存储库

public class AppRepository {

    // ...  non-relevent code is omitted

    private static Executor executor = Executors.newSingleThreadExecutor();

    public interface OnTextListener {
        void onTextReceived(String text);
    }

    public void getNoteText(int id, OnTextListener listener) {
        executor.execute(() -> {
            String text = mDb.noteDao().loadSingle(id); // mDb is the database instance in repository 
            // trigger the listener in the ViewModel
            listener.onTextReceived(text);
        });
    }

}

视图模型

public class MainViewModel extends AndroidViewModel {

    // ...  non-relevent code is omitted

    public void getNoteText(int id, AppRepository.OnTextListener listener) {
        mRepository.getNoteText(id, listener);
    }
}

活动

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...  non-relevent code is omitted

        // Retrieve single data from Room database
        int id = 39;
        mViewModel.getNoteText(id, new AppRepository.OnTextListener() {
            @Override
            public void onTextReceived(String text) {
                // The retrieved text from Room database
                Log.d(TAG, "onTextReceived: " + text);
                new Handler(Looper.getMainLooper()) {
                }.post(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM