如何在片段而不是活动中使用 setContentView
Posted
技术标签:
【中文标题】如何在片段而不是活动中使用 setContentView【英文标题】:How to use setContentView in fragment instead of an activity 【发布时间】:2020-07-30 21:26:47 【问题描述】:亲爱的 ***ers :)
AllAssetsFragment
从 MainActivity 打开。在这个片段中,我无法正确设置 setContentView()
和 getApplicationContext()
。
我知道有问题。一些代码适用于正常活动,但它们不适用于此片段。
所有资产片段:
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class AllAssetsFragment extends Fragment
public AllAssetsFragment()
private static final String HI = "https://uniqueandrocode.000webhostapp.com/hiren/favouritelist.php";
private List<AssetsItem>assetsItems;
private RecyclerView recyclerView;
AssetsAdapter adapter;
private JsonArrayRequest request;
private RequestQueue requestQueue;
public static FavoritesDatabase favoritesDatabase;
Button btn;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
return inflater.inflate(R.layout.fragment_allassets, container, false);
recyclerView = (RecyclerView)getView().findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
// +++ PROBLEM 1: Context doesn't work (same on Problem 3 and 4) +++
recyclerView.setLayoutManager(new LinearLayoutManager(this));
assetsItems = new ArrayList<>();
btn=(Button)getView().findViewById(R.id.favbtn);
btn.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
// +++ PROBLEM 2: This code doesn't work to open Fragment from Fragment +++
startActivity(new Intent(AllAssetsFragment.this, FavoritesFragment.class));
);
favoritesDatabase = Room.databaseBuilder(getActivity().getApplicationContext(), FavoritesDatabase.class, "myfavdb").allowMainThreadQueries().build();
getData();
private void getData()
request = new JsonArrayRequest(HI, new Response.Listener<JSONArray>()
@Override
public void onResponse(JSONArray response)
JSONObject jsonObject = null;
for (int i = 0; i < response.length(); i++)
try
JSONObject ob = response.getJSONObject(i);
AssetsItem pr = new AssetsItem(ob.getInt("id"),
ob.getString("product_name"),
ob.getString("product_img"));
assetsItems.add(pr);
catch (JSONException e)
e.printStackTrace();
setupData(assetsItems);
, new Response.ErrorListener()
@Override
public void onErrorResponse(VolleyError error)
);
// +++ PROBLEM 3: Context doesn't work +++
requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
private void setupData(List<AssetsItem>assetsItems)
adapter=new AssetsAdapter(assetsItems,getActivity().getApplicationContext());
recyclerView.setAdapter(adapter);
这里是我们的第二个片段:FavoritesFragment:
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* A simple @link Fragment subclass.
*/
public class FavoritesFragment extends Fragment
public FavoritesFragment()
private RecyclerView rv;
private FavoritesAdapter adapter;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
return inflater.inflate(R.layout.fragment_favorites, container, false);
rv=(RecyclerView)getView().findViewById(R.id.rec);
rv.setHasFixedSize(true);
// +++ PROBLEM 4: doesn't work +++
rv.setLayoutManager(new LinearLayoutManager(this));
getFavData();
private void getFavData()
List<FavoritesItem>favoritesItems=AllAssetsFragment.favoritesDatabase.favoritesDao().getFavoritesData();
adapter = new FavoritesAdapter(favoritesItems,getActivity().getApplicationContext());
rv.setAdapter(adapter);
【问题讨论】:
请不要仅仅因为您使用 android-studio 标签而标记问题:Android Studio 标签应该仅在您对 IDE 本身有疑问时使用,而不是您在其中编写(或想要编写)的任何代码。请参阅 when is it appropriate to remove an IDE tag、How do I avoid misusing tags? 和 the tagging guide。请改用 [android] 或其他相关标签。 【参考方案1】:不要在片段中使用setContentView()
。你应该在onCreateView()
中初始化你的视图,就像你已经做的那样。
关于应用程序上下文,我看到您正在将它传递给您的适配器。我认为您不需要那里的应用程序上下文,因为片段的上下文就足够了。你可以传requireContext()
。
您还需要从onCreateView()
设置您的RecyclerView
和适配器。
【讨论】:
感谢您的建议,我在上面的代码中添加了它,但仍然有 3 个上下文问题和 1 个从现有片段打开片段的问题。为了使它更容易,我用第二个片段添加到上面的代码中。如果你能解决这些问题,那就太好了! :) @Lulu96 我同意 Minas Mina 的观点。最近Android Studio的lint推荐使用requireContext
来获取一个Context。尝试将getActivity().getApplicationContext()
或this
替换为requireContext()
。【参考方案2】:
这些是您在代码中犯的错误。
AllAssetsFragment
将下面的行移到onCreateView()
方法的底部。它是一个 return 语句,因此,它必须是函数中的最后一件事。
return inflater.inflate(R.layout.fragment_allassets, container, false);
您不能使用startActivity(...)
来启动片段。此方法严格用于启动活动。要了解如何启动片段,请查看this awesome answer。
将下面几行中的this
替换为getActivity()
:
recyclerView.setLayoutManager(new LinearLayoutManager(this));
requestQueue = Volley.newRequestQueue(this);
收藏片段
将下面一行中的this
替换为getActivity()
:
rv.setLayoutManager(new LinearLayoutManager(this));
附录:
要在活动(在您的情况下为 MainActivity)中启动片段,请执行以下步骤:
在您的 activity_main.xml 文件中,创建一个 FrameLayout 来容纳您的片段,您可以给它一个 id:container
。如果您不知道如何执行此操作,只需粘贴以下代码:
<FrameLayout
android:layout_
android:layout_
android:id="@+id/container" />
当你想从一个活动中启动一个片段时,只需使用这个代码sn-p:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.container, new AllAssetsFragment());
transaction.commit();
当你想从另一个 Fragment 启动一个 Fragment 时,只需使用这段代码 sn-p:
FragmentTransaction transaction = getActivity().getFragmentManager().beginTransaction();
transaction.replace(R.id.container, new AllAssetsFragment());
transaction.commit();
在上面的代码 sn-ps 中,如果 getFragmentManager()
不起作用或者您使用的是 AndroidX,请改用 getSupportFragmentManager()
。
【讨论】:
所有其他建议都很好!但我不知道如何启动AllAssetsFragment
和FavoritesFragment
课程。重要提示:它们已经使用下面代码中的名称制作。只有这一行是错的,你能帮我写一个有效的吗? ;) 谢谢! startActivity(getActivity(AllAssetsFragment, FavoritesFragment.class));
我已经更新了我的答案。我添加了一些关于如何启动片段的步骤。
如果有什么问题,请告诉我。我会解释的。【参考方案3】:
您不要在需要在onCreateView
方法中返回视图的片段中调用setContentView
。你已经完成了。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_allassets, container, false);
对于getApplicationContext
,您需要致电getActivity()
喜欢这个
getActivity().getApplicationContext()
【讨论】:
感谢您的建议,我在上面的代码中添加了它,但仍然有 3 个上下文问题和 1 个从现有片段打开片段。以上是关于如何在片段而不是活动中使用 setContentView的主要内容,如果未能解决你的问题,请参考以下文章