我尝试在 onCreate() 方法中创建新线程并启动它,但应用程序卡住并且消息仍然相同(无法访问主线程上的数据库,因为它可能会长时间锁定 UI。)
也尝试了 Runnable 和 Handler 相同的消息 我搜索了很多相同的问题,发现 runOnUIThread 仍然是相同的问题
任何有帮助的文章或视频请引用 您想要查看的任何缺失代码也请引用它 提前致谢。
package com.example.android.popularmovies;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import com.example.android.popularmovies.DataBase.AppDatabase;
import com.example.android.popularmovies.DataBase.FavoriteMovies;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class MainActivity extends AppCompatActivity {
private ArrayList<ListItem> arrayMovies = new ArrayList<>();
private RecyclerView mRecyclerView;
private RecyclerViewAdapter adapter;
private RecyclerViewAdapterFavorite adapterFavorite;
private String dataRetrieved;
private static final String TAG = "MAINACTIVITY";
private String top_rated = "http://api.themoviedb.org/3/movie/top_rated?api_key=*****";
private String MoviesURL = "http://api.themoviedb.org/3/movie/popular?api_key=*****";
private AppDatabase mDb;
private List<FavoriteMovies> allFavoriteMovies=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDb=AppDatabase.getInstance(getApplicationContext());
networkUtilites(false);
getArrayMovies();
RecyclerViewAdapter();
MainActivity.this.runOnUiThread(new Runnable()
{
@Override
public void run() {
allFavoriteMovies= mDb.taskDao().loadAllTasks();
}
});
for(int i=0;i<allFavoriteMovies.size();i++)
{
System.out.println(allFavoriteMovies.get(i).getTitle());
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.sorting_menu, menu);
return true;
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.most_popular:
Toast.makeText(this, "MostPopularClicked", Toast.LENGTH_SHORT).show();
arrayMovies.clear();
networkUtilites(false);
getArrayMovies();
RecyclerViewAdapter();
return true;
case R.id.top_rated:
Toast.makeText(this, "TopRatedClicked", Toast.LENGTH_SHORT).show();
arrayMovies.clear();
networkUtilites(true);
getArrayMovies();
RecyclerViewAdapter();
return true;
case R.id.favorite:
Toast.makeText(this, "Favorite", Toast.LENGTH_SHORT).show();
RecyclerViewAdapterFavorite();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void networkUtilites(Boolean check) {
NetworkUtilites ob = new NetworkUtilites();
if (check) {
ob.setMoviesURL(top_rated);
} else {
ob.setMoviesURL(MoviesURL);
}
try {
dataRetrieved = ob.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void getArrayMovies() {
try {
if (!dataRetrieved.equals(null)) {
JSONObject parentObject = new JSONObject(dataRetrieved);
JSONArray parentArray = parentObject.getJSONArray("results");
//System.out.println(parentArray.length());
for (int i = 0; i < parentArray.length(); i++) {
JSONObject movieDetails = parentArray.getJSONObject(i);
String poster_path = "http://image.tmdb.org/t/p/w500";
poster_path += movieDetails.getString("poster_path");
String original_title = movieDetails.getString("original_title");
String overview = movieDetails.getString("overview");
int vote_average = movieDetails.getInt("vote_average");
String release_date = movieDetails.getString("release_date");
int id =movieDetails.getInt("id");
ListItem ob = new ListItem(original_title, poster_path, overview, vote_average, release_date,id);
arrayMovies.add(ob);
}
}
} catch (Exception e) {
}
}
public void RecyclerViewAdapter() {
adapter = new RecyclerViewAdapter(this, arrayMovies);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(adapter);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
}
public void RecyclerViewAdapterFavorite()
{
if (allFavoriteMovies != null) {
adapterFavorite = new RecyclerViewAdapterFavorite(this, allFavoriteMovies);
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setAdapter(adapterFavorite);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
}
}
}
TaskDao
package com.example.android.popularmovies.DataBase;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
@Dao
public interface TaskDao
{
@Query("SELECT * From movies")
List<FavoriteMovies> loadAllTasks();
@Query("DELETE From movies")
void deleteallTasks();
@Insert
void insertMovie(FavoriteMovies favoriteMovies);
@Delete
void deleteMovie(FavoriteMovies favoriteMovies);
}
最喜欢的电影
package com.example.android.popularmovies.DataBase;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
@Entity(tableName = "movies")
public class FavoriteMovies
{
@PrimaryKey
private int id;
private String image;
private String title;
private String overview;
@Ignore
public FavoriteMovies(String image, String title, String overview) {
this.image = image;
this.title = title;
this.overview = overview;
}
public FavoriteMovies(int id, String image, String title, String overview) {
this.id = id;
this.image = image;
this.title = title;
this.overview = overview;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getOverview() {
return overview;
}
public void setOverview(String overview) {
this.overview = overview;
}
}
应用程序数据库
package com.example.android.popularmovies.DataBase;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {FavoriteMovies.class},version = 1,exportSchema = false)
public abstract class AppDatabase extends RoomDatabase
{
private static final String DATABASE_NAME="FavouriteMovies";
private static final Object LOCK = new Object();
private static AppDatabase sInstance;
public static AppDatabase getInstance(Context context)
{
if(sInstance==null)
{
synchronized (LOCK){
sInstance= Room.databaseBuilder(context.getApplicationContext(),AppDatabase.class,AppDatabase.DATABASE_NAME)
.build();
}
}
return sInstance;
}
public abstract TaskDao taskDao();
}
堆栈跟踪:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.popularmovies, PID: 5342
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.popularmovies/com.example.android.popularmovies.MainActivity}: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
最佳答案
卡住的原因是因为您将任务放在 runonuithread 上,这意味着它与 UI 运行在同一线程上,并且会阻塞系统。
您可以尝试https://developer.android.com/reference/android/os/AsyncTask 。它有一个易于使用的 API,用于短时间的多线程目的。
另一种方法是在 onCreate 中创建新的 java 线程,该线程不在 ui 线程上运行。
Thread t = new Thread(new Runnable(){yourcodehere})
t.start()
关于java - 无法在主线程上访问数据库,因为它可能会长时间锁定 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58788885/