我目前在我的Android应用中遇到ClassCastException而导致"活动无法转换为接口"。 这是我的代码:
Logcat说,在MovieGridFragment的onAttach部分抛出异常" this.clickListener =(clickInterfaceHelper)上下文;"。
我的界面:
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId); }
片段类:
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
@Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
MainActivity:
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);
movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
movieAdapter adapter = new movieAdapter(getActivity(),movieDataList);
adapter.notifyDataSetChanged();
movieGridView.setAdapter(adapter);
movieGridView.setSelection(index);
movieGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(clickListener != null)
clickListener.clickOnItem(position);
}
});
return rootView;
}
@Override
public void onSaveInstanceState(Bundle outState) {
index = movieGridView.getFirstVisiblePosition();
outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
super.onSaveInstanceState(outState);
}}
and mainactivity:
public class MainActivity extends AppCompatActivity implements clickInterfaceHelper {
public static String sorterString = null;
public static String urlBase = "https://api.themoviedb.org/3/movie/";
public static String urlFinal = null;
RequestQueue requestQueue;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, new MovieGridFragment())
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu_act, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.m_popularity_action) {
if(sorterString != "popular?") {
sorterString = "popular?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_action_voter) {
if(sorterString != "top_rated?") {
sorterString = "top_rated?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_favorite_btn) {
if(sorterString != "favorite") {
SQLiteOpenHelper helper = new movieDataDbHelper(this);
SQLiteDatabase database = helper.getReadableDatabase();
Cursor cursor= database.query(movieDataContract.contractEntry.TABLE_NAME,
new String[] {
movieDataContract.contractEntry.ID,
movieDataContract.contractEntry.IMG_PATH},null,null,null,null,null);
if(cursor.getCount() == 0) {
Toast.makeText(this, "there are no favorite movies yet!",Toast.LENGTH_SHORT).show();
} else {
sorterString = "favorite";
showFavoriteFragment();
}
database.close();
helper.close();
cursor.close();
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void showFavoriteFragment() {
favoriteMoviesDetailsFragment fragment = new favoriteMoviesDetailsFragment();
try {
getFragmentManager().beginTransaction().replace(R.id.activity_container,fragment).commit();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
outState.putString("SORTER", sorterString);
outState.putInt("POSITION",movieData.movieDataPosition);
super.onSaveInstanceState(outState, outPersistentState);
}
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
@Override
public void clickOnItem(int id) {
movieData.movieDataPosition = id;
if(movieData.movieDataArray == null) {
movieRequest();
} else {
Intent intent = new Intent(this, detailsActivity.class);
intent.putExtra("FRAGMENT","MOVIE");
startActivity(intent);
}
}
@Override
public void favoriteMovieItem(int movieId) {
movieData.dbPosition = movieId;
Intent intent = new Intent(this,detailsActivity.class);
intent.putExtra("FRAGMENT","favorite");
startActivity(intent);
} }
答案 0 :(得分:3)
传入的上下文不一定是您的活动。它可能是一个包装器,包含各种主题和其他覆盖。你永远不能假设当传递一个Context时,你传递了一个Activity。如果需要对单击处理程序的引用,请编写setClickHandler函数并显式调用它。
即使它是Activity,应用程序也不知道 - 在那一点上它是一个Context。由于第1段的原因,您需要明确地转换它,这可能不起作用(并且可能适用于某些版本的操作系统而不适用于其他版本)。
答案 1 :(得分:3)
你可以试试这个
this.clickListener = (MainActivity) getActivity();
您获得FragmentActivity并将其转换为MainActivity
编辑:
我建议你在片段中添加一个函数,如:
public void setListener(clickInterfaceHelper listener) {
this.clickListener = listener;
}
在你的活动中:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
MovieGridFragment fragment = new MovieGridFragment();
fragment.setListener(this); // some change here
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, fragment)
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
.... no relevant functions
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridfragment.setListener(this); // some change here
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
希望这有帮助。
答案 2 :(得分:0)
尝试将您的界面放在片段类中。
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
@Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId);
}
}
答案 3 :(得分:-1)
对于所有Android初学者,您可以使用如下所述的界面。
定义界面
public interface CallBack {
String stringValue(String s);
}
在片段中,
Callback mCallback;
在片段的onAttach(上下文上下文)方法中,
mCallback = (Callback) context; // Casting to the activity
mcallback.stringValue("Your message");
然后在你的Activity中,你必须实现你将获得的接口
ClassCastException异常
public class MainActivity implements CallBack{
@Override
public String stringValue(String s) {
// Here you will get the value from the fragment
return s;
}
}
不建议直接使用接口在两个片段之间传递值。您应该在传递值时将活动用作中介。