I'm using flow library(https://github.com/square/flow) to display screens in my app. I have a screen with map view, I implemented it like this:
public class MainView extends LinearLayout implements OnMapReadyCallback {
private MapView mMapView;
private MainScreen mScreen;
public MainView(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(VERTICAL);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mScreen = Flow.getKey(this);
mMapView = (MapView)findViewById(R.id.map);
mMapView.onCreate(mScreen.getGoogleMapState());
mMapView.getMapAsync(this);
mMapView.onResume();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
sInstance = null;
MainScreen screen = Flow.getKey(this);
if(mMapView != null) {
mMapView.onPause();
mMapView.onSaveInstanceState(mScreen.getGoogleMapState());
mMapView.onDestroy();
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
mScreen.setMapReady(true);
}
}
My MainScreen class is saving map state:
public class MainScreen implements Parcelable {
private Bundle googleMapState = new Bundle();
private boolean mMapReady;
public MainScreen(Context context) {
Flow.get(context).setHistory(History.emptyBuilder().push(this).build(), Direction.REPLACE);
}
public Bundle getGoogleMapState() {
return googleMapState;
}
public void setGoogleMapState(Bundle googleMapState) {
this.googleMapState = googleMapState;
}
public void setMapReady(boolean mapReady) {
mMapReady = mapReady;
}
public boolean isMapReady() {
return mMapReady;
}
protected MainScreen(Parcel in) {
googleMapState = in.readBundle();
mMapReady = in.readInt() == 1;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeBundle(googleMapState);
dest.writeInt(mMapReady ? 1 : 0);
}
#SuppressWarnings("unused")
public static final Parcelable.Creator<MainScreen> CREATOR = new Parcelable.Creator<MainScreen>() {
#Override
public MainScreen createFromParcel(Parcel in) {
return new MainScreen(in);
}
#Override
public MainScreen[] newArray(int size) {
return new MainScreen[size];
}
};
}
But the google map view is recreated every time app is resumed. What I am doing wrong? I want that google map would be resumed just the way it was before leaving app.
Related
I trying to find a way to save the state of checkbox to Room Database.But when I click on checkbox and reopen the app,it's state doesn't change.I don't know where I went wrong.
I have searched the previous questions but could not find the solution. Below is my code and thanks.
Model class
#Entity(tableName = "todo_table")
public class Todo {
#PrimaryKey(autoGenerate = true)
public int id;
public String title;
public Boolean isChecked;
public Todo(String title, Boolean isChecked) {
this.title = title;
this.isChecked = isChecked;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Boolean getChecked() {
return isChecked;
}
public void setChecked(Boolean checked) {
isChecked = checked;
}
}
DAO
#Dao
public interface TodoDAO {
#Insert
void Insert(Todo todo);
#Update
void Update(Todo todo);
#Query("SELECT * FROM todo_table ORDER BY id ASC")
LiveData<List<Todo>> getAllTodo();
}
TodoDatabase
#Database(entities = Todo.class,version = 1,exportSchema = false)
public abstract class TodoDatabase extends RoomDatabase {
private static TodoDatabase instance;
public abstract TodoDAO todoDAO();
public static synchronized TodoDatabase getInstance(Context context){
if(instance == null){
instance = Room.databaseBuilder(context.getApplicationContext(),
TodoDatabase.class,"todo_database").fallbackToDestructiveMigration()
.addCallback(roomCallBack)
.build();
}
return instance;
}
private static RoomDatabase.Callback roomCallBack = new RoomDatabase.Callback(){
#Override
public void onCreate(#NonNull SupportSQLiteDatabase db) {
super.onCreate(db);
new PopulateDbAsyncTask(instance).execute();
}
};
private static class PopulateDbAsyncTask extends AsyncTask<Void,Void,Void> {
private TodoDAO todoDAO;
private PopulateDbAsyncTask(TodoDatabase database) {
todoDAO = database.todoDAO();
}
#Override
protected Void doInBackground(Void... voids) {
return null;
}
}
}
TodoRepository
public class TodoRepository {
private TodoDAO todoDAO;
private LiveData<List<Todo>> todo;
public TodoRepository(Application application){
TodoDatabase database = TodoDatabase.getInstance(application);
todoDAO = database.todoDAO();
todo = todoDAO.getAllTodo();
}
public void insert(Todo todo){
new InsertNoteAsyncTask(todoDAO).execute(todo);
}
public LiveData<List<Todo>> getTodo() {
return todo;
}
public void update(Todo todo){
new UpdateTodoAsyncTask(todoDAO).execute(todo);
}
private static class InsertNoteAsyncTask extends AsyncTask<Todo,Void,Void> {
private TodoDAO todoDAO;
private InsertNoteAsyncTask(TodoDAO todoDAO){
this.todoDAO = todoDAO;
}
#Override
protected Void doInBackground(Todo... todos) {
todoDAO.Insert(todos[0]);
return null;
}
}
private static class UpdateTodoAsyncTask extends AsyncTask<Todo,Void,Void> {
private TodoDAO todoDAO;
private UpdateTodoAsyncTask(TodoDAO todoDAO){
this.todoDAO = todoDAO;
}
#Override
protected Void doInBackground(Todo... todos) {
todoDAO.Update(todos[0]);
return null;
}
}
}
TodoViewModel
public class TodoViewModel extends AndroidViewModel {
private TodoRepository repository;
private LiveData<List<Todo>> todo;
public TodoViewModel(#NonNull Application application) {
super(application);
repository = new TodoRepository(application);
todo = repository.getTodo();
}
public void insert(Todo todo){
repository.insert(todo);
}
public void update(Todo todo){
repository.update(todo);
}
public LiveData<List<Todo>> getTodo(){
return todo;
}
}
TodoAdapter
public class TodoAdapter extends RecyclerView.Adapter<TodoAdapter.ViewHolder>{
private List<Todo> todos = new ArrayList<>();
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(TodoItemBinding.inflate(LayoutInflater.from(parent.getContext()),parent,false));
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Todo currentTodo = todos.get(holder.getAbsoluteAdapterPosition());
holder.binding.tvTitle.setText(currentTodo.getTitle());
holder.binding.checkBox.setChecked(currentTodo.getChecked());
holder.binding.checkBox.setOnCheckedChangeListener(null);
holder.binding.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked){
holder.binding.checkBox.setChecked(true);
}else{
holder.binding.checkBox.setChecked(false);
}
}
});
}
#Override
public int getItemCount() {
if(todos != null){
return todos.size();
}else{
return 0;
}
}
public void setTodos(List<Todo> todos){
this.todos = todos;
notifyDataSetChanged();
}
class ViewHolder extends RecyclerView.ViewHolder{
private TodoItemBinding binding;
public ViewHolder(TodoItemBinding bind){
super(bind.getRoot());
this.binding = bind;
}
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private TodoItemBinding todoItemBinding;
private TodoViewModel todoViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
todoItemBinding = TodoItemBinding.inflate(getLayoutInflater());
View view = binding.getRoot();
setContentView(view);
RecyclerView recyclerView = binding.recyclerView;
recyclerView.setLayoutManager(new LinearLayoutManager(this));
TodoAdapter todoAdapter = new TodoAdapter();
recyclerView.setAdapter(todoAdapter);
todoViewModel = new ViewModelProvider(this).get(TodoViewModel.class);
todoViewModel.getTodo().observe(this, new Observer<List<Todo>>() {
#Override
public void onChanged(List<Todo> todos) {
todoAdapter.setTodos(todos);
}
});
binding.btnAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addTodo();
}
});
todoItemBinding.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Boolean isChecked = todoItemBinding.checkBox.isChecked();
Todo todo;
if (isChecked){
todo = new Todo(binding.editText.getText().toString(), true);
}else{
todo = new Todo(binding.editText.getText().toString(), false);
}
todoViewModel.update(todo);
}
});
}
private void addTodo() {
String title = binding.editText.getText().toString();
Todo todo = new Todo(title,false);
todoViewModel.insert(todo);
binding.editText.setText("");
closeKeyboard();
}
private void closeKeyboard(){
View view = this.getCurrentFocus();
if (view != null) {
InputMethodManager manager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
manager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
}
Using SharedPrefs would save a lot of time. Change the following code:
Inside MainActivity
public void onClick(View v) {
Boolean isChecked = todoItemBinding.checkBox.isChecked();
Todo todo;
if (isChecked){
todo = new Todo(binding.editText.getText().toString(), true);
}else{
todo = new Todo(binding.editText.getText().toString(), false); }
todoViewModel.update(todo);
}
with this
public void onClick(View v) {
Boolean isChecked =PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean("checkBox1", false);
checkBox1.setChecked(checked);
Todo todo;
if (isChecked){
todo = new Todo(binding.editText.getText().toString(), true);
}else{
todo = new Todo(binding.editText.getText().toString(), false); }
todoViewModel.update(todo);
}
I am sending Request on fragment to receive Store Item data from Server which contains urls of images like below
public class StoreFragment extends BaseFragment<FragmentStoreBinding, StoreViewModel> implements StoreNavigator {
#Inject
StoreViewModel viewModel;
#Inject
StoreAdapter storeAdapter;
#Inject
StoreVO storeVO;
public static final String TAG = StoreFragment.class.getSimpleName();
private FragmentStoreBinding binding;
public static StoreFragment newInstance() {
Bundle args = new Bundle();
StoreFragment fragment = new StoreFragment();
fragment.setArguments(args);
return fragment;
}
public static StoreFragment newInstance(StoreVO storeVO) {
Bundle args = new Bundle();
StoreFragment fragment = new StoreFragment();
args.putString(INTENT_EXTRA_STOREVO, new Gson().toJson(storeVO)); //put string, int, etc in bundle with a key value
fragment.setArguments(args);
return fragment;
}
#Override
public int getBindingVariable() {
return BR.viewModel;
}
#Override
public int getLayoutId() {
return R.layout.fragment_store;
}
#Override
public StoreViewModel getViewModel() {
return viewModel;
}
#Override
public void goBack() {
getBaseActivity().onFragmentDetached(TAG);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel.setNavigator(this);
storeAdapter.setStoreFragment(this);
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume(){
super.onResume();
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = getViewDataBinding();
if (getArguments().containsKey(INTENT_EXTRA_STOREVO)) {
storeVO = new Gson().fromJson(getArguments().getString(INTENT_EXTRA_STOREVO), StoreVO.class);
}
initView();
}
#Override
public void onPrefClicked(String prefSn, boolean sendRequest) {
storeVO.setPrefSn(prefSn);
storeVO.setSearchKeyCode1(prefSn);
switch (prefSn) {
case EAT_PREF_SN:
binding.eatCb.setChecked(true);
break;
case DRINK_PREF_SN:
binding.drinkCb.setChecked(true);
break;
case PLAY_PREF_SN:
binding.playCb.setChecked(true);
break;
case WATCH_PREF_SN:
binding.watchCb.setChecked(true);
break;
case WALK_PREF_SN:
binding.walkCb.setChecked(true);
break;
default:
binding.allCb.setChecked(true);
}
if(sendRequest){
//initStoreView();
viewModel.requestStoreList(storeVO);
}
}
private void initView() {
binding.storeRv.setLayoutManager(new GridLayoutManager(getActivity().getApplicationContext(), 2));
binding.storeRv.setItemAnimator(new DefaultItemAnimator());
binding.storeRv.setAdapter(storeAdapter);
initStoreView();
onPrefClicked(storeVO.getPrefSn(), false);
}
private void initStoreView(){
viewModel.requestStoreList(storeVO);
subscribeStoreListLiveData();
}
private void subscribeStoreListLiveData() {
viewModel.getStoreListLiveData().observe(this, storeList -> {
viewModel.addStoreList(storeList);
if (storeList != null) {
binding.totalCount.setText(String.valueOf(storeList.size()));
}
});
}
}
view model for this fragment is like below
public class StoreViewModel extends BaseViewModel<StoreNavigator> {
public final ObservableList<StoreVO> storeObservableList = new ObservableArrayList<>();
// MutableLiveData는 LifeCycle에 의존하여 메모리관리 등 여러 장점을 지님
private final MutableLiveData<List<StoreVO>> storeListLiveData;
public StoreViewModel(BaseApplication baseApplication) {
super(baseApplication);
storeListLiveData = new MutableLiveData<>();
}
public void requestStoreList(StoreVO storeVO) {
getCompositeDisposable().add(
getRetrofitService().selectStoreInfoList(storeVO)
.subscribeOn(getNetworkHelper().getSchedulerIo())
.observeOn(getNetworkHelper().getSchedulerUi())
.subscribe(storeListLiveData::setValue, throwable -> Dlog.e(throwable.getMessage())));
}
public MutableLiveData<List<StoreVO>> getStoreListLiveData() {
return storeListLiveData;
}
public void addStoreList(List<StoreVO> storeList) {
storeObservableList.clear();
storeObservableList.addAll(storeList);
}
public ObservableList<StoreVO> getStoreObservableList() {
return storeObservableList;
}
public void onFilterClick() {
getNavigator().goToSearchFilterActivity();
}
public void onPrefTypeClicked(String prefSn) {
getNavigator().onPrefClicked(prefSn, true);
}
}
and storeList was attached by adapter like below
public class StoreAdapter extends RecyclerView.Adapter<StoreAdapter.StoreViewHolder> {
private List<StoreVO> storeList;
private StoreFragment storeFragment;
public StoreAdapter() {
this.storeList = new ArrayList<>();
}
#NonNull
#Override
public StoreViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
StoreItemListBinding binding = StoreItemListBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new StoreViewHolder(binding);
}
#Override
public void onBindViewHolder(#NonNull StoreViewHolder holder, int index) {
final int position = index;
holder.bind(storeList.get(index));
holder.itemView.setOnClickListener(v ->
storeFragment.goToPlaceDetailActivity(storeList.get(position)));
}
#Override
public void onViewDetachedFromWindow(#NonNull StoreViewHolder holder) {
holder.viewDetached();
super.onViewDetachedFromWindow(holder);
}
#Override
public int getItemCount() {
return storeList.size();
}
// Override for duplicated bugs
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
// Override for duplicated bugs
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
public List<StoreVO> getStoreList() {
return storeList;
}
public void setStoreList(List<StoreVO> storeList) {
this.storeList = storeList;
}
public void clearItems() {
storeList.clear();
}
public void addItems(List<StoreVO> storeList) {
this.storeList.addAll(storeList);
notifyDataSetChanged();
}
public StoreFragment getStoreFragment() {
return storeFragment;
}
public void setStoreFragment(StoreFragment storeFragment) {
this.storeFragment = storeFragment;
}
class StoreViewHolder extends RecyclerView.ViewHolder {
private StoreItemListBinding binding;
private ArrayList<String> urlList;
StoreViewHolder(StoreItemListBinding binding) {
super(binding.getRoot());
this.urlList = new ArrayList<>();
this.binding = binding;
initImageSlider();
}
public void bind(StoreVO storeVO) {
binding.priceTv.setText(String.valueOf(storeVO.getReprMenuPrice()));
binding.addrTv.setText(storeVO.getAreaDetailNm());
binding.nameTv.setSelected(true);
binding.nameTv.setText(storeVO.getStoreNm());
binding.scoreTv.setText(String.format(Locale.KOREA, "%.1f", storeVO.getStoreScore()));
addImageSlider(storeVO);
}
private void initImageSlider() {
binding.storeSlider.setIndicatorAnimation(IndicatorAnimations.FILL); //set indicator animation by using SliderLayout.Animations. :WORM or THIN_WORM or COLOR or DROP or FILL or NONE or SCALE or SCALE_DOWN or SLIDE and SWAP!!
binding.storeSlider.setScrollTimeInSec(3); //set scroll delay in seconds :
}
private void addImageSlider(StoreVO storeVO) {
generateUrlList(storeVO);
setSliderViews();
}
private void generateUrlList(StoreVO storeVO) {
urlList.clear();
if (storeVO.getStoreImageUrlList().size() == 0) {
String url = CommonUtils.createDefaultImageUrl();
urlList.add(url);
} else {
for (String imageUrl : storeVO.getStoreImageUrlList()) {
String url = CommonUtils.createStoreImageUrl(storeVO.getStoreSn(), imageUrl);
urlList.add(url);
}
}
}
private void setSliderViews() {
binding.storeSlider.clearSliderViews();
for (String url : urlList) {
DefaultSliderView sliderView = new DefaultSliderView(binding.getRoot().getContext().getApplicationContext());
sliderView.setImageUrl(url);
sliderView.setImageScaleType(ImageView.ScaleType.CENTER_CROP);
//sliderView.setOnSliderClickListener(view -> Dlog.e(url));
//at last add this view in your layout :
binding.storeSlider.addSliderView(sliderView);
}
}
private void viewDetached() {
urlList.clear();
binding.storeSlider.clearSliderViews();
}
}
}
After storeList updated, Text on items of Recylerview was changed but ImageSlider on item was not changed.
I checked that viewDetached() on StoreViewHolder was called but images remaind on previous store item
i was using image sliders in github: https://github.com/smarteist/android-image-slider
what should i do to updated images for imagesliders on recycler-view items???
To simplify my question,
i was using RecyclerView to show items which contains image slider. That image slider load images through URL. After receive new itemList(storeList) from server, itemList(storeList) for RecylerView and URLs in Item(Store) for ImageSlider was changed but not updated on ImageSlider.
Through debugging, i checked that new UrlList was generated and setSliderViews was called but remains previous image
How do i fix my code to update Images on RecylerView's items?
I am using a custom gridview adapter to show images with volley singleton. But when I run it it returns the onErrorResponse. It looks like the adapter is not even set properly, is it something with where i set the adapter? I have tried setting it in onCreate but same error.
The adapter class looked fine so I think the problem is in MainActivity.
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private final int THUMBNAIL_SIZE = 250;
private final String KEY = "IMAGE";
ArrayList<Bitmap> bitmaps = new ArrayList<Bitmap>();
private static final String URLS[] = {
"http://10.0.2.2/Android%20A4_1/germany.png",
"http://10.0.2.2/Android%20A4_1/indonesia.png",
"http://10.0.2.2/Android%20A4_1/japan.png",
"http://10.0.2.2/Android%20A4_1/sarawak.png",
"http://10.0.2.2/Android%20A4_1/singapore.png",
"http://10.0.2.2/Android%20A4_1/switzerland.png",
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for(int i = 0; i<URLS.length; i++) {
LoadingImages(URLS[i]);
}
}
private void LoadingImages(String url) {
ImageLoader imageLoader = MySingleton.getInstance(getApplicationContext()).getImageLoader();
imageLoader.get(url, new ImageLoader.ImageListener() {
#Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
Bitmap image = response.getBitmap();
Bitmap thumbnail = ThumbnailUtils.extractThumbnail(image, THUMBNAIL_SIZE, THUMBNAIL_SIZE);
bitmaps.add(thumbnail);
GridView gridView = (GridView)findViewById(R.id.grid_layout);
final ImageAdapter imageAdapter = new ImageAdapter(MainActivity.this, bitmaps);
gridView.setAdapter(imageAdapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(getApplicationContext(), Main2Activity.class);
intent.putExtra(KEY, URLS[i]);
startActivity(intent);
}
});
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e("error", error.getMessage());
}
});
}
}
The Adapter class:
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Bitmap> bitmaps;
public ImageAdapter(Context context, ArrayList<Bitmap> bitmaps) {
this.mContext = context;
this.bitmaps = bitmaps;
}
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
view = layoutInflater.inflate(R.layout.griditems, null);
MyViewHolder myViewHolder = new MyViewHolder(view);
view.setTag(myViewHolder);
}
MyViewHolder myViewHolder = (MyViewHolder)view.getTag();
myViewHolder.img.setImageBitmap(bitmaps.get(i));
return view;
}
public class MyViewHolder {
public ImageView img;
public MyViewHolder(View view) {
img = view.findViewById(R.id.image1);
}
}
}
My Singleton:
public class MySingleton {
private static MySingleton instance;
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private static Context context;
private MySingleton(Context context){
this.context = context;
requestQueue = Volley.newRequestQueue(context);
imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> cache = new LruCache<>(6);
#Override
public Bitmap getBitmap(String url) {
Bitmap bmp = cache.get(url);
if (bmp == null) {
System.out.println("Not in cache");
} else {
System.out.println("In cache");
}
return bmp;
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
System.out.println("Put in cache");
cache.put(url, bitmap);
}
});
}
public static synchronized MySingleton getInstance(Context context) {
if (instance == null) {
instance = new MySingleton(context);
}
return instance;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
}
Main2Activity:
public class Main2Activity extends AppCompatActivity {
private ImageView imageView;
private final String KEY = "IMAGE";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
imageView = (ImageView)findViewById(R.id.imageView);
Bundle bundle = getIntent().getExtras();
String url = bundle.getString(KEY);
LoadingImages(url);
}
private void LoadingImages(String url) {
final ImageLoader imageLoader = MySingleton.getInstance(getApplicationContext()).getImageLoader();
imageLoader.get(url, new ImageLoader.ImageListener() {
#Override
public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
Bitmap bitmap = response.getBitmap();
imageView.setImageBitmap(bitmap);
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
}
});
}
}
change This methods
#Override
public int getCount() {
return 0;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
To
#Override
public int getCount() {
return bitmaps.size;
}
#Override
public Object getItem(int i) {
return bitmaps.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
I am follow this link tutorial [https://developer.qualcomm.com/software/snapdragon-neural-processing-engine-ai/getting-started and i am able to download all model image but my requirement is now i need how to display gallery image in grid view my code is for model overview fragment:
public class ModelOverviewFragment extends Fragment {
public static final String EXTRA_MODEL = "model";
enum MenuRuntimeGroup {
SelectCpuRuntime(NeuralNetwork.Runtime.CPU),
SelectGpuRuntime(NeuralNetwork.Runtime.GPU),
SelectDspRuntime(NeuralNetwork.Runtime.DSP);
public static int ID = 1;
public NeuralNetwork.Runtime runtime;
MenuRuntimeGroup(NeuralNetwork.Runtime runtime) {
this.runtime = runtime;
}
}
private GridView mImageGrid;
private ModelImagesAdapter mImageGridAdapter;
private ModelOverviewFragmentController mController;
private TextView mDimensionsText;
private TextView mModelNameText;
private Spinner mOutputLayersSpinners;
private TextView mClassificationText;
private TextView mModelVersionText;
public static ModelOverviewFragment create(final Model model) {
final ModelOverviewFragment fragment = new ModelOverviewFragment();
final Bundle arguments = new Bundle();
arguments.putParcelable(EXTRA_MODEL, model);
fragment.setArguments(arguments);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_model, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mImageGrid = (GridView) view.findViewById(R.id.model_image_grid);
mImageGridAdapter = new ModelImagesAdapter(getActivity());
mImageGrid.setAdapter(mImageGridAdapter);
mImageGrid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Bitmap bitmap = mImageGridAdapter.getItem(position);
mController.classify(bitmap);
}
});
mModelNameText = (TextView) view.findViewById(R.id.model_overview_name_text);
mModelVersionText = (TextView) view.findViewById(R.id.model_overview_version_text);
mDimensionsText = (TextView) view.findViewById(R.id.model_overview_dimensions_text);
mOutputLayersSpinners = (Spinner) view.findViewById(R.id.model_overview_layers_spinner);
mClassificationText = (TextView) view.findViewById(R.id.model_overview_classification_text);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
final Model model = getArguments().getParcelable(EXTRA_MODEL);
mController = new ModelOverviewFragmentController(
(Application) getActivity().getApplicationContext(), model);
}
#Override
public void onCreateOptionsMenu(android.view.Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
final SNPE.NeuralNetworkBuilder builder = new SNPE.NeuralNetworkBuilder(
(Application) (getActivity().getApplicationContext()));
for (MenuRuntimeGroup item : MenuRuntimeGroup.values()) {
if (builder.isRuntimeSupported(item.runtime)) {
menu.add(MenuRuntimeGroup.ID, item.ordinal(), 0, item.runtime.name());
}
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getGroupId() == MenuRuntimeGroup.ID) {
final MenuRuntimeGroup option = MenuRuntimeGroup.values()[item.getItemId()];
mController.setTargetRuntime(option.runtime);
}
return super.onOptionsItemSelected(item);
}
#Override
public void onStart() {
super.onStart();
mController.attach(this);
}
#Override
public void onStop() {
mController.detach(this);
super.onStop();
}
public void addSampleBitmap(Bitmap bitmap) {
if (mImageGridAdapter.getPosition(bitmap) == -1) {
mImageGridAdapter.add(bitmap);
mImageGridAdapter.notifyDataSetChanged();
}
}
public void setNetworkDimensions(Map<String, int[]> inputDimensions) {
mDimensionsText.setText(Arrays.toString(inputDimensions.get("data")));
}
public void displayModelLoadFailed() {
mClassificationText.setVisibility(View.VISIBLE);
mClassificationText.setText(R.string.model_load_failed);
Toast.makeText(getActivity(), R.string.model_load_failed, Toast.LENGTH_SHORT).show();
}
public void setModelName(String modelName) {
mModelNameText.setText(modelName);
}
public void setModelVersion(String version) {
mModelVersionText.setText(version);
}
public void setOutputLayersNames(Set<String> outputLayersNames) {
mOutputLayersSpinners.setAdapter(new ArrayAdapter<>(
getActivity(), android.R.layout.simple_list_item_1,
new LinkedList<>(outputLayersNames)));
}
public void setClassificationResult(String[] classificationResult) {
if (classificationResult.length > 0) {
mClassificationText.setText(
String.format("%s: %s", classificationResult[0], classificationResult[1]));
}
mClassificationText.setVisibility(View.VISIBLE);
}
public void setLoadingVisible(boolean visible) {
mClassificationText.setVisibility(visible ? View.VISIBLE : View.GONE);
if (visible) {
mClassificationText.setText(R.string.loading_network);
}
}
public void displayModelNotLoaded() {
Toast.makeText(getActivity(), R.string.model_not_loaded, Toast.LENGTH_SHORT).show();
}
public void displayClassificationFailed() {
Toast.makeText(getActivity(), R.string.classification_failed, Toast.LENGTH_SHORT).show();
}
private static class ModelImagesAdapter extends ArrayAdapter<Bitmap> {
public ModelImagesAdapter(Context context) {
super(context, R.layout.model_image_layout);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.model_image_layout, parent, false);
} else {
view = convertView;
}
final ImageView imageView = ImageView.class.cast(view);
imageView.setImageBitmap(getItem(position));
return view;
}
}
}
for image loading code :
public class LoadImageTask extends AsyncTask<File, Void, Bitmap> {
private final ModelOverviewFragmentController mController;
private final File mImageFile;
public LoadImageTask(ModelOverviewFragmentController controller, final File imageFile) {
mController = controller;
mImageFile = imageFile;
}
#Override
protected Bitmap doInBackground(File... params) {
return BitmapFactory.decodeFile(mImageFile.getAbsolutePath());
}
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
mController.onBitmapLoaded(mImageFile, bitmap);
}
}
/*public class LoadImageTask extends AsyncTask{
private final ModelOverviewFragmentController mController;
private File path;
public LoadImageTask(ModelOverviewFragmentController controller, File jpeg)
{
mController=controller;
path=jpeg;
}
#Override
protected Bitmap doInBackground(Object... params) {
Bitmap bitmap = null;
File file = new File(
Environment.getExternalStorageDirectory().getAbsolutePath() + path);
if(file.exists()){
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
Log.d("ImagePath",bitmap.toString());
}
return bitmap;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mController.onBitmapLoaded(path,result);
}
}
for model :
public class Model implements Parcelable {
public static final Uri MODELS_URI = Uri.parse("content://snpe/models");
// public static final Uri MODELS_URI=Uri.parse("content://mtp://[usb:002,029]/Internal%20shared%20storage/DCIM");
public static final String INVALID_ID = "null";
public File file;
public String[] labels;
public File[] rawImages;
public File[] jpgImages;
public String name;
public File meanImage;
protected Model(Parcel in) {
name = in.readString();
file = new File(in.readString());
final String[] rawPaths = new String[in.readInt()];
in.readStringArray(rawPaths);
rawImages = fromPaths(rawPaths);
final String[] jpgPaths = new String[in.readInt()];
in.readStringArray(jpgPaths);
jpgImages = fromPaths(jpgPaths);
meanImage = new File(in.readString());
labels = new String[in.readInt()];
in.readStringArray(labels);
}
public Model() {}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(file.getAbsolutePath());
dest.writeInt(rawImages.length);
dest.writeStringArray(toPaths(rawImages));
dest.writeInt(jpgImages.length);
dest.writeStringArray(toPaths(jpgImages));
dest.writeString(meanImage.getAbsolutePath());
dest.writeInt(labels.length);
dest.writeStringArray(labels);
}
private File[] fromPaths(String[] paths) {
final File[] files = new File[paths.length];
for (int i = 0; i < paths.length; i++) {
files[i] = new File(paths[i]);
}
return files;
}
private String[] toPaths(File[] files) {
final String[] paths = new String[files.length];
for (int i = 0; i < files.length; i++) {
paths[i] = files[i].getAbsolutePath();
}
return paths;
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<Model> CREATOR = new Creator<Model>() {
#Override
public Model createFromParcel(Parcel in) {
return new Model(in);
}
#Override
public Model[] newArray(int size) {
return new Model[size];
}
};
#Override
public String toString() {
return name.toUpperCase();
}
}
To load SD card images in grid view, please make few changes in loadImageSamples method of ModelOverviewFragmentController.java. Currently, the images are picked from snpe folder inside internal storage of the device and are populated on Grid View. To get all the images from the gallery, create AsyncTask class to load images from the Gallery to the Grid View with the help of Content Provider.
Please use this link https://stackoverflow.com/a/10877404 for code reference to load images on grid view.
Hope this helps!
Thank You
Im building a simple aplication with a recycleView/CardLayout, i followeed this tutorial.
I see many questions answered for the card click, but what i need is to handle diferent actions when the user clicks the title or the user clicks on the image in each card.
This is what i have at the moment:
public class SimiliarPlantsAdapter extends RecyclerView.Adapter<SimiliarPlantsAdapter.PlantViewHolder>{
ArrayList<Plant> plants = new ArrayList<Plant>();
Context context;
public static class PlantViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView plantName;
CheckBox plantCheck;
ImageView plantPhoto;
PlantViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
plantName = (TextView)itemView.findViewById(R.id.plantName);
plantCheck = (CheckBox)itemView.findViewById(R.id.plantCheck);
plantPhoto = (ImageView)itemView.findViewById(R.id.plantPhoto);
}
}
#Override
public PlantViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.similiar_photo_row, viewGroup, false);
PlantViewHolder pvh = new PlantViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PlantViewHolder holder, int position) {
holder.plantName.setText(plants.get(position).getSpecie());
holder.plantCheck.setText("Are you sure this is the plant?");
Log.d("foto",String.valueOf(holder.plantName));
String urlFoto = "http://10.0.2.2:3000/images/" + holder.plantName.getText().toString() + "/Thumbnail.jpg";
Picasso.with(context)
.load(urlFoto)
.resize(250, 250)
.into(holder.plantPhoto);
}
#Override
public int getItemCount() {
return plants.size();
}
public SimiliarPlantsAdapter(ArrayList<Plant> plants,Context context) {
this.plants = plants;
this.context = context;
}
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
}
MY Activity
public class SimiliarPhotos extends AppCompatActivity implements IResult {
RecyclerView rv;
LinearLayoutManager llm;
ArrayList<Plant> plants = new ArrayList<Plant>();
SimiliarPlantsAdapter adapter;
VolleyService mVolleyService;
IResult mResultCallback = null;
final String GETREQUEST = "GETCALL";
//login url connection
final String URL = "http://10.0.2.2:3000/plants";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_similiar_photos);
rv = (RecyclerView)findViewById(R.id.rv);
llm = new LinearLayoutManager(this);
llm.setAutoMeasureEnabled(true);
rv.setLayoutManager(llm);
initializeAdapter();
initVolleyCallback();
mVolleyService = new VolleyService(mResultCallback,this);
mVolleyService.getDataVolley(GETREQUEST,URL);
}
#Override
public void notifySuccess(String requestType, JSONObject response) {
Log.d("resposta",response.toString());
}
#Override
public void notifySuccess(String requestType, JSONArray response) {
Log.d("resposta",response.toString());
}
#Override
public void notifyError(String requestType, VolleyError error) {
Log.d("resposta",error.toString());
}
void initVolleyCallback(){
mResultCallback = new IResult() {
#Override
public void notifySuccess(String requestType, JSONObject response) {
}
#Override
public void notifySuccess(String requestType, JSONArray response) {
Plant plant;
Log.d("ENTERED","ENTEREDHERE1");
// iterate over the JSONArray response
for (int i=0; i < response.length(); i++) {
try {
JSONObject object = response.getJSONObject(i); // get the individual object from JSONArray
int id = Integer.parseInt(object.getString("id")); // get the unique identifier from the object
String specie = object.getString("specie"); // get the name of the specie from the object
String description = object.getString("description"); // get the description of the object
plant = new Plant(id,specie,description); // construct the object
Log.d("plant",String.valueOf(plant));
plants.add(plant); // add the object to the arraylist so it can be used on the cardLayout
} catch (JSONException e) {
Log.d("ENTERED",e.toString());
e.printStackTrace();
}
}
adapter.notifyDataSetChanged();
}
#Override
public void notifyError(String requestType, VolleyError error) {
Log.d("resposta",error.toString());
}
};
}
public void initializeAdapter(){
Log.d("plants",String.valueOf(plants.size()));
adapter = new SimiliarPlantsAdapter(plants,SimiliarPhotos.this);
rv.setAdapter(adapter);
}
}
The volley init is the request, not so important for the question, since i get the data correctly
First, you have to add the interface to handle the clicks in your Adapter and add it in your constructor :
public class SimiliarPlantsAdapter extends RecyclerView.Adapter<SimiliarPlantsAdapter.PlantViewHolder>{
private OnItemClickListener listener;
public interface OnItemClickListener {
void onTitleClicked(int position, String title, View clickedview);
void onImageClicked(int position, View clickedview);
}
}
public SimiliarPlantsAdapter(ArrayList<Plant> plants,Context context, OnItemClickListener listener ) {
this.plants = plants;
this.context = context;
this.listener = listener;
}
Now, you have to set these on your onClick method inside your onBindViewHolder:
holder.plantName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (onItemClickListener != null) {
onItemClickListener.onTitleClicked(holder.getAdapterPosition(), plants.get(position).getSpecie(), view);
}
}
});
holder.plantPhoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (onItemClickListener != null) {
onItemClickListener.onItemClicked(holder.getAdapterPosition(), view);
}
}
});
}
}
And finally, implement the interface in your Activity:
public class SimiliarPhotos extends AppCompatActivity implements IResult, SimiliarPlantsAdapter.OnItemClickListener {
#Override
public void onTitleClicked(int position, String title, View clickedView) {
//Handle your title click here
}
#Override
public void onImageClicked(int position, View clickedView) {
//Handle your image click here
}
public void initializeAdapter(){
Log.d("plants",String.valueOf(plants.size()));
adapter = new SimiliarPlantsAdapter(plants,SimiliarPhotos.this, SimilarPhotos.this);
rv.setAdapter(adapter);
}