The basic problem here is that you are trying to return the result of an asynchronous computation synchronously. It is not possible. You can't return something that you don't have yet!
So what should you?
The simple solution is to do the database operation synchronously; i.e. do it in the current thread rather than using new Thread(...).start(). Just move the code that is in your run() method inline.
(You would get the same effect by calling join() on the thread before the final return in you code. But you would be creating and destroying a thread for no good reason. It is inefficient.)
However, if you need to do the database operation asynchronously, you could use a CompletableFuture (javadoc) as follows:
public CompletableFuture<double[]> findbyidTodo(Context context , String loc) {
final CompletableFuture<double[]> future = new CompletableFuture<>();
new Thread(new Runnable() {
@Override
public void run() {
Todo todo = TodoRoomDatabase.getInstance(context)
.todoDao()
.findTodoById(loc);
if (todo != null) {
future.complete(new double[]{todo.getLatitude(), todo.getLongitude()});
} else {
future.complete(null);
}
}).start();
return future;
}
Then the caller can do this:
CompletableFuture<double[]> future = findbyidTodo(...);
// Do some other stuff
double[] result = future.get(); // This blocks until the future has been completed.
Note that it is only worthwhile doing this if the database call is likely to take a significant amount of time, AND there actually is "other stuff" for the calling thread to do while the database call is in progress. If not ... then it is better to do the database operation synchronously.
Finally, if you are going to do this asynchronously, it would be more efficient to use a thread pool or executor service rather than creating a new thread for each database operation. Look at the javadocs for ExecutorService and Executors. (Creating and destroying threads is relatively expensive.)