I am trying to make a gridview on LayoutInflater, when i test my app, it always crashes.
here is my code :
public class Level1 extends Fragment {
public static Fragment newInstance(Context context) {
Level1 f = new Level1();
return f;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.grid_layout, null);
GridView gridView = (GridView) root.findViewById(R.id.grid_view);
gridView.setAdapter(new ImageAdapter(root.getContext()));
}
I think, my problem is in "setAdapter". I can't use context "xxx.this". I've try to change setAdapter context with "getContext" and "getApplicationContext" but it still crashes.
when i delete "setAdapter" my app working but without gridView.
My ImageAdapter is look like this :
public class ImageAdapter extends BaseAdapter {
private Context mContext;
public Integer[] mThumbIds = {
R.drawable.pic_1, R.drawable.pic_2,
R.drawable.pic_3, R.drawable.pic_4,
R.drawable.pic_5, R.drawable.pic_6,
R.drawable.pic_7, R.drawable.pic_8,
R.drawable.pic_9, R.drawable.pic_10,
R.drawable.pic_11, R.drawable.pic_12,
R.drawable.pic_13, R.drawable.pic_14,
R.drawable.pic_15
};
// Constructor
public ImageAdapter(Context c){
mContext = c;
}
#Override
public int getCount() {
return mThumbIds.length;
}
#Override
public Object getItem(int position) {
return mThumbIds[position];
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(mThumbIds[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new GridView.LayoutParams(70, 70));
return imageView;
}
}
Please help me..
Please set a breakpoint on this line GridView gridView = (GridView) root.findViewById(R.id.grid_view); and start debugging your app (in eclipse it's the button on the left side of the button you usually use to start your application). When the breakpoint is reached please step over one step and see if gridView is null. For me this looks like the most reasonable source of your error. But without a detailled error message it's hard to say, so please update your post.
if you are getting OUTOFMEMORY exception its generally because you are using large size images. you will have to sample it down. and in fragment you have to use getactivity() for context.
Related
My project is a tuition management book in this I list all students with their photos, names, IDs, classes in Activity by using a custom listView it runs well but when adding more student it showing lag in listview scrolling. using the below adapter I am facing scroll lag in listView. I reduce the size of the image(under 500kb)which store in the SQLite database but still it's not working smoothly. **
Adapter code
public class MyListAdapter extends BaseAdapter {
private Context context;
private int layout;
private ArrayList<slmodel> recordlist;
public MyListAdapter(Activity context, int layout, ArrayList<slmodel> recordlist) {
this.context = context;
this.layout= layout;
this.recordlist = recordlist;
}
#Override
public int getCount() {
return recordlist.size();
}
#Override
public slmodel getItem(int position) {
return recordlist.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder{
ImageView imageView;
TextView name,id, sclass;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row=convertView;
ViewHolder holder=new ViewHolder();
if(row==null)
{
LayoutInflater inflater=(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row=inflater.inflate(layout,null);
holder.name=row.findViewById(R.id.bname);
holder.id=row.findViewById(R.id.sid);
holder.sclass =row.findViewById(R.id.scourse);
holder.imageView=row.findViewById(R.id.imageView);
row.setTag(holder);
}
else{
holder=(ViewHolder)row.getTag();
}
slmodel model=recordlist.get(position);
holder.name.setText(model.getName());
holder.id.setText(model.getId().toString());
holder.sclass.setText(model.getsclass());
byte[] recordimgae=model.getImgae();
Bitmap bitmap= BitmapFactory.decodeByteArray(recordimgae,0,recordimgae.length);
holder.imageView.setImageBitmap(bitmap);
return row;
}
}
Welcome to SO, and congratulations on posting your first question.
use image loading libraries like Picasso or Glide
with these libraries, you can:
resize your image
use caches to decrease loading time
handle background thread automatically for loading and converting bitmaps.
sample for Glide:
Glide.with(context)
.load(recordImage)
.asBitmap()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.imageView);
This is example from Android for beginners book. I think that problem is with mNoteAdapter but I can't find where it exactly is. I tried to use adapter from other source and it was working(I mean click) so I could see at least log in logcat. How does mNoteAdapter affect on possibility of seeing users click by app? How can I find where problem is?
mNoteAdapter = new NoteAdapter();
ListView listNote = (ListView) findViewById(R.id.listView);
listNote.setAdapter(mNoteAdapter);
listNote.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View view, int
whichItem, long id) {
Log.e("CLICK", "CliCK");
}
});
}
Here is a piece of NoteAdapter class
public class NoteAdapter extends BaseAdapter {
List<Note> noteList = new ArrayList<Note>();
#Override
public int getCount() {
}
#Override
public Note getItem(int whichItem) {
}
#Override
public long getItemId(int whichItem) {
}
#Override
public View getView(int whichItem, View view, ViewGroup viewGroup) {
if (view == null) {
LayoutInflater inflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.listitem, viewGroup, false);
}
TextView txtTitle = (TextView) view.findViewById(R.id.txtTitle);
ImageView ivImportant = (ImageView) view.findViewById(R.id.imageViewImportant);
Note tempNote = noteList.get(whichItem);
if (!tempNote.isImportant()) {
ivImportant.setVisibility(View.GONE);
}
txtTitle.setText(tempNote.getTitle());
return view;
}
public void addNote(Note n) {
}
}
There are many ways to display items as list on Android..
--> ListView, RecyclerView etc.
Lists need a source right? Let's assume that your source is an array of 1000 elements. Your ListView has to have as many columns to display all of them right?
Adapter is responsible for taking the array, and assigning each element to every list placeholders
This row was added to the top of .xml file
android:descendantFocusability="blocksDescendants"
I used fragment in my app and i'm using SQLite to save local data. But when I finished saving data, and I swipe the page, my listView is not refreshed with new data (Only showing old data). I have tried to provide a method notifyDataSetChanged() on my adapter, but it's not working.
My Base Adapter class :
public class LocalDataAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<LocalDataBean> data;
private static LayoutInflater inflater = null;
public LocalDataAdapter(Activity a, ArrayList<LocalDataBean> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setItem(ArrayList<LocalDataBean> data){
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView nama_konsumen = (TextView) v.findViewById(R.id.nama_konsumen);
TextView no_telp = (TextView) v.findViewById(R.id.no_telp);
TextView no_hp_cdma = (TextView) v.findViewById(R.id.no_hp_cdma);
TextView no_hp_gsm = (TextView) v.findViewById(R.id.no_hp_gsm);
LocalDataBean obj = (LocalDataBean) getItem(position);
nama_konsumen.setText(obj.getNamaKonsumen());
no_telp.setText(obj.getNoTelp());
no_hp_cdma.setText(obj.getNoCMDA());
no_hp_gsm.setText(obj.getNoGSM());
return v;
}
}
My fragment class :
public class LocalDataFragment extends Fragment {
View view;
Activity act;
SQLHandlerBean utilSql;
ArrayList<LocalDataBean> localdatabean = new ArrayList<LocalDataBean>();
LocalDataAdapter adapter;
ListView list;
public static final String TAG = LocalDataFragment.class.getSimpleName();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_local_data, null);
act = getActivity();
list = (ListView) view.findViewById(R.id.listViewLocalData);
utilSql = new SQLHandlerBean(this.act);
adapter = new LocalDataAdapter(act, localdatabean);
localdatabean = new ArrayList<LocalDataBean>();
list.setAdapter(adapter);
if (utilSql.ReadAllLocalData().size() < 1) {
Toast.makeText(act, "DATA EMPTY!", Toast.LENGTH_LONG).show();
} else {
localdatabean = utilSql.ReadAllLocalData();
Log.e(TAG, "TOTAL DATA : "+localdatabean.size());
adapter.setItem(localdatabean);
adapter.notifyDataSetChanged();
}
return view;
}
}
Is adapter.notifyDataSetChanged() placement correct?
No, the placement is not in the right place.
As you have placed the notifyDataSetChanged() inside of the onCreateView() method. It will be only invoked 1st time the fragment is launched.
Rather you can add a refresh button in your layout (or in you action bar). And along with the insertion/deletion method of the data, place the notifyDataSetChanged() at the bottom of the click event of that button.
By doing this user can refresh the page whenever they want.
And if you want to refresh the page by swipping the view then, SwipeRefreshLaoyout could be a perfect alternative.
You can check this blog.
I am using following code for my ListView..
My FragmentActivity
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.home, container, false);
listView = (ListView) view.findViewById(R.id.listView);
listView.setAdapter(new CustomArrayAdapterForHome(mContext,questions));
return view;
}
Here is the Adapter for ListView
#SuppressLint("DefaultLocale")
public class CustomArrayAdapterForHome extends EndlessAdapter
{
private final LayoutInflater inflator;
protected ImageLoader imageLoader;
private DisplayImageOptions options;
private RotateAnimation rotate=null;
private View pendingView = null;
public CustomArrayAdapterForHome(Context ctx,ArrayList<Question> questionList)
{
super( new ArrayAdapter<Question>(ctx, R.layout.question_adapter_layout, questionList));
inflator = mContext.getLayoutInflater();
imageLoader = ImageLoader.getInstance();
options = new DisplayImageOptions.Builder()
.cacheInMemory()
.cacheOnDisc()
.showImageForEmptyUri(R.drawable.user_male)
.displayer(new RoundedBitmapDisplayer(5))
.build();
rotate=new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF,
0.5f);
rotate.setDuration(600);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);
}
class ViewHolder
{
// MY CODE
}
#Override
public int getCount() {
return questions.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final Question question = questions.get(position);
final OpenionUser myUser = question.getUser();
// MY CODE
return view;
}
#Override
protected View getPendingView(ViewGroup parent)
{
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, null);
pendingView = row.findViewById(android.R.id.text1);
pendingView.setVisibility(View.GONE);
pendingView=row.findViewById(R.id.throbber);
pendingView.setVisibility(View.VISIBLE);
startProgressAnimation();
return(row);
}
private void startProgressAnimation()
{
if (pendingView!=null)
{
pendingView.startAnimation(rotate);
}
}
#Override
protected void appendCachedData()
{
}
#Override
protected boolean cacheInBackground() throws Exception
{
getQuestions();
return true;
}
}
The above code is just behaving like simple ListView, cacheInBackground Or getPendingView are not getting called. FurtherMore I want to add a headerView too and its not working either.
What am I missing in this?
Most of the code that you have here does not belong in an EndlessAdapter. Quoting the documentation:
It is designed to wrap around another adapter, where you have your "real" data. Hence, it follows the Decorator pattern, augmenting your current adapter with new Endless Technology(TM).
So, first, create a regular ArrayAdapter, and get all the styling and stuff that you want (e.g., your getView() implementation). Then, create an EndlessAdapter subclass that adds in the "endlessness".
Of note:
An EndlessAdapter subclass should not override getView(), as that is where the endless behavior is added
An EndlessAdapter subclass should not override getCount(), as that is managed by the EndlessAdapter implementation itself
You may wish to examine the sample app to see how it implements EndlessAdapter subclasses.
Or, since EndlessAdapter will not work with header views, you may simply need to switch to a different endless list solution or roll your own.
If you check out this answer.
Lazy load of images in ListView
Fedor has provided a tutorial on how to lazy load with image view.
But he said it can be used with Gallery with minor modifications.
How do i go about doing this with minor modifications?
Ive Tried this so far.
This is the BaseAdapter
public class LazyAdapter extends BaseAdapter {
private Activity activity;
private String[] data;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader;
public LazyAdapter(Activity a, String[] d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return data.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.item, null);
TextView text=(TextView)vi.findViewById(R.id.text);;
ImageView image=new ImageView(this.activity);
text.setText("item "+position);
imageLoader.DisplayImage(data[position], activity, image);
return vi;
}
}
And then in my activity i do this..
LazyAdapter adapter=new LazyAdapter(MainMenu.this, myRemoteImages);
((Gallery) findViewById(R.id.gallery))
.setAdapter(adapter);
It doesnt seem to be working though.
Nothing is showing up
Here is something that I managed to work out. After implementing Fedor's code in a GridView, you must be aware that in the ImageLoader class file there is a class named decodeFile(). In that class Fedor's code automatically resizez the image so that it can become a small thumbnail. You have just to comment the "rescaling" part and your image will appear in full in the GalleryView.