App keeps crashing when i try to load image - kotlin

Please i have been trying this for weeks now. I have a fragment that displays notifications. But it time i click on the notification my app crashes. it points me the line below Picasso.get().load(user!!.getImage()).placeholder(R.drawable.profile).into(imageView)
and it says: java.lang.IllegalArgumentException: Path must not be empty
From logcat, using picasso seems to be the problem but i am new to programming and i have no idea what exacty to do. Please help me. Thank you
Below is the complete code for my notificationAdapter
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(mContext).inflate(R.layout.notifications_item_layout , parent,false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val notification = mNotification[position]
if(notification.getText().equals("Admirers you")){
holder.text.text = "Admirers you"
}
else if(notification.getText().equals("Liked your post")){
holder.text.text = "Liked your post"
}
else if (notification.getText().contains("commented:")){
holder.text.text = notification.getText().replace("commented:", "commented: ")
}
else{
holder.text.text = notification.getText()
}
userInfo(holder.profileImage, holder.fullname, notification.getUserId())
if(notification.isIsPost()){
holder.postImage.visibility = View.VISIBLE
getPostImage(holder.postImage, notification.getPostId())
}
else{
holder.postImage.visibility = View.GONE
}
holder.itemView.setOnClickListener {
if(notification.isIsPost()){
val editor = mContext.getSharedPreferences("PREFS", Context.MODE_PRIVATE).edit()
editor.putString("postId", notification.getPostId())
editor.apply()
(mContext as FragmentActivity).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, PostDetailsFragment()).commit()
}
else{
val editor = mContext.getSharedPreferences("PREFS", Context.MODE_PRIVATE).edit()
editor.putString("profileId", notification.getUserId())
editor.apply()
(mContext as FragmentActivity).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, ProfileFragment()).commit()
}
}
}
override fun getItemCount(): Int {
return mNotification.size
}
inner class ViewHolder(#NonNull itemView: View) : RecyclerView.ViewHolder(itemView)
{
var postImage: ImageView
var profileImage : CircleImageView
var fullname : TextView
var text : TextView
init {
postImage = itemView.findViewById(R.id.notification_post_image)
profileImage = itemView.findViewById(R.id.notifications_profile_image)
fullname = itemView.findViewById(R.id.fullname_notification)
text = itemView.findViewById(R.id.comment_notification)
}
}
private fun userInfo(imageView: ImageView, fullname: TextView, publisherId:String)
{
val usersRef =
FirebaseDatabase.getInstance().reference
.child("Users")
.child(publisherId)
usersRef.addValueEventListener(object : ValueEventListener
{
override fun onDataChange(p0: DataSnapshot)
{
if (p0.exists())
{
val user = p0.getValue(User::class.java)
Picasso.get().load(user!!.getImage()).placeholder(R.drawable.profile).into(imageView)
fullname.text = user.getfullname()
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
private fun getPostImage(imageView: ImageView, postID:String)
{
val postRef =
FirebaseDatabase.getInstance()
.reference.child("Posts")
.child(postID)
postRef.addValueEventListener(object : ValueEventListener
{
override fun onDataChange(p0: DataSnapshot)
{
if (p0.exists()) {
val post = p0.getValue<Post>(Post::class.java)
Picasso.get().load(post!!.getpostimage()).placeholder(R.drawable.profile)
.into(imageView)
}
}
override fun onCancelled(p0: DatabaseError) {
}
})
}
}
And also my notification fragment
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="Fragments.NotificationsFragment">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/app_bar_layout_notifications"
android:background="#color/white">
<androidx.appcompat.widget.Toolbar
android:id="#+id/notifications_toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="4dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
android:background="#android:color/white">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Notifications"
android:textSize="18sp"
android:maxLines="1"
android:textStyle="bold"
android:textColor="#android:color/black"
android:layout_centerVertical="true"/>
</RelativeLayout>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_notifications"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_below="#+id/app_bar_layout_notifications">
</androidx.recyclerview.widget.RecyclerView>
Then in case you need more info, here's my notifications item layout. Thank you
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/notifications_profile_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="#drawable/profile">
</de.hdodenhof.circleimageview.CircleImageView>
<LinearLayout
android:layout_toEndOf="#+id/notifications_profile_image"
android:layout_toStartOf="#+id/notification_post_image"
android:layout_centerVertical="true"
android:layout_marginStart="5dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/fullname_notification"
android:textStyle="bold"
android:textColor="#color/teal_200"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
<TextView
android:id="#+id/comment_notification"
android:textStyle="bold"
android:textColor="#color/teal_200"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<ImageView
android:id="#+id/notification_post_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentEnd="true">
</ImageView>

I don't know Picasso, so I can't tell you what the problem is*. (I don't even know Android, which I guess this is for.) But since you're new to programming, it seems to me that what you need to know is how to find out the problem for yourself — how to debug — so here are some hints that I hope will help.
You've done the right thing in starting with the logs; if you have an exception with a stack trace, that's always helpful in narrowing down the problem. But your case hasn't narrowed it down enough, because that one line is doing many different things. So the simplest thing to try would be to split that line up — then the stack trace's line number will narrow it down more finely.
You could simply wrap the line, e.g.:
Picasso.get()
.load(user!!.getImage())
.placeholder(R.drawable.profile)
.into(imageView)
Then you'll be able to tell which of those main operations triggered the exception. (Of course, the operation that gave the exception might not be the one you need to change — but either way you need to understand the problem before you can fix it.)
If that's not enough, then there are several approaches you could take. But the one I usually end up falling back on is the most general: logging. Whether you're working on a desktop app, a mobile app, a web app, a microservice, a stand-alone app, or whatever, there's almost always a way to print out some text in such a way that you can see it on screen or in a file. As I said, I don't know Android, but this question seems to show how you can do that; in other environments, you might use one of several logging libraries (java.util.logging, log4j…), or just the basic println(). But however you do it, there's bound to be a way you can see some of the intermediate values — and being able to see what's going on is always valuable when debugging.
You could try printing out the user (or, if that doesn't have a simple string representation, their name or something else that might give you a clue). Then the image, ditto. The the results of the load() call. And so on. Of course, that means restructuring your code a bit, e.g.:
val picasso = Picasso.get()
println("picasso = $picasso")
println("user = $user")
val image = user!!.getImage()
println("image = $image")
val loaded = picasso.load(image)
println("loaded = $loaded")
println("profile = ${R.drawable.profile}")
val placeholder = loaded.placeholder(R.drawable.profile)
println("placeholder = $placeholder")
println("imageView = $imageView")
placeholder.into(imageView)
(Substituting whatever logging method works in your case. I'm overdoing it here, of course. But I hope you get the idea.)
For the record, Kotlin's also() gives a way of doing the above without having to name all the temporary variables, or split up the chain of calls:
Picasso.get()
.also{ println("picasso = $it") }
.also{ println("user = $user") }
.load(user!!.getImage().also{ println("image = $it") } )
.also{ println("loaded = $it") }
.placeholder(R.drawable.profile.also{ println("profile = $it") })
.also{ println("placeholder = $it") }
.into(imageView.also{ println("imageView = $it") })
However, that can get unwieldy pretty quickly, so I wouldn't normally recommend it.
Either way, in all likelihood one of the values you print out won't be what you expect, or you'll be able to spot something that doesn't look right, and that will give you enough info to identify the problem — or at least, to direct your attention to some other part of the code that you can then debug in the same way.
Once you've fixed the problem and the code is behaving as expected, you can remove the logging. However, it's often better to leave some logging code in. (Especially if you're using a logging library that lets you set different levels, so you can log this at a low level that you won't normally get to see.) Then, when you need to track down some other problem in the code, it's much easier to see what's going on.
(* From the exception message, I'd suspect an issue with the user!!.getImage() part. But that's just a blind guess.)

Related

RecyclerView not updating via Live Data Observer

I am trying to update the recyclerView adapter in the observe response of live data object but it is not updating the UI rather if I debug it, it starts updating the UI.
Looks like adding a delay make it work or reassigning the recyclerView items adapter also works but I didn't understand why is the notifyDataSetChanged or notifyItemRangeChanged is not working
following is the code I am using
adapter = MyAdapter(listOf())
binding.recyclerView.adapter = adapter
viewModel = ViewModelProvider(this).get(HomeViewModel::class.java)
viewModel.data.observe(this, {
adapter.setData(it)
// This updates the UI, but this is not the right way to do so
//binding.recyclerViewData.adapter = adapter
})
Adapter class where I update the data
fun setData(data: MutableList<DataModelRoom>) {
this.data= data
notifyItemRangeChanged(0, data.size)
}
ViewModel part of the code
var data: MutableLiveData<MutableList<DataModel>> = MutableLiveData()
/* This is part of init method */
viewModelScope.launch {
Amplify.Hub.subscribe(HubChannel.DATASTORE) { event ->
if (event.name == DataStoreChannelEventName.READY.toString()) {
isAmplifyDataReady.postValue(true)
data.postValue(repository.getDataFromAmplify())
}
Log.i(Logging.TAG_AMPLIFY, "event: $event")
}
/* Starting the DataStore Syncing */
Amplify.DataStore.start(
{ Log.i(Logging.TAG_AMPLIFY, "DataStore started") },
{ Log.e(Logging.TAG_AMPLIFY, "Error starting DataStore", it) }
)
}
Layout part of the recyclerView
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="152dp"
android:orientation="horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textViewView" />
I think you're over complicating the issue. Use a ListAdapter<T, K> (included with the platform and call adapter.submitList(pass_the_new_list_here) and have the (required) DiffUtil.Callback handle the differences and update what's needed.

how to set regex in EditText with Android two way binding?

Hello I wonder how to set regex in EditText with Android two way binding
my regex
val VALID_PASSWOLD_REGEX_ALPHA_NUM: Pattern = Pattern.compile("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[$#$!%*#?&])[A-Za-z[0-9]$#$!%*#?&]{8,32}$")
my viewModel
val passwordText = MutableLiveData<String>("")
my xml
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="#null"
android:onTextChanged="#{(text, start, before, count) -> signUpViewModel.onPasswordChanged(text)}"
android:hint="#string/sign_up_password"
android:text="#={signUpViewModel.passwordText}"
android:textSize="22dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/name_text" />
My short thought is that it should be received from onTextChange and processed, but I can't think of a better way, so I ask this question
Could you please introduce me another way?
I just did it using android:onTextChanged Thanks

I got my Activity Dark When I use "Navigation-Drawer" KOTLIN

I'm using a navigation component but when I click an Item to load an activity it starts in dark screen and I don't know what's going on?
View works only when I press the square to "resume my app" and I don't really know where's the mistake
This is my code
navigation.xml
<activity
android:id="#+id/mn_log_out"
android:name="mx.MyApp.android.LogOutMessageActivity"
android:label="LogOutMessageActivity" />
mx.MyApp.android.LogOutMessageActivity
#SuppressLint("ResourceType", "CommitPrefEdits")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val builder = AlertDialog.Builder(this)
builder.setTitle(resources.getString(R.string.log_out_title))
builder.setMessage(resources.getString(R.string.log_out_description))
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
when (which) {
DialogInterface.BUTTON_POSITIVE -> logOut()
}
}
builder.setPositiveButton(resources.getString(R.string.yes), dialogClickListener)
builder.setNegativeButton(resources.getString(R.string.no), dialogClickListener)
dialog = builder.create()
dialog.show()
}
The problem was on the build.gradle
I made downgrade to this libraries. We need to report this issue on the newest version
THIS
implementation "androidx.navigation:navigation-fragment-ktx:2.3.0"
implementation "androidx.navigation:navigation-ui-ktx:2.3.0"
INSTEAD
implementation "androidx.navigation:navigation-fragment-ktx:2.3.1"
implementation "androidx.navigation:navigation-ui-ktx:2.3.1"

Fragment is given a null on recyclerView in onCreateView()

Application based on one activity and some fragments.
When fragment starts application is crashed with log:
java.lang.RuntimeException: Unable to start activity ComponentInfo{ru.alexsuvorov.paistewiki/ru.alexsuvorov.paistewiki.StartDrawer}: java.lang.NullPointerException
...
Caused by: java.lang.NullPointerException
at ru.alexsuvorov.paistewiki.Fragment.NewsFragment.onCreateView(NewsFragment.java:42)
There i just initialize some array positions and just try display it
Now i edit code
public class NewsFragment extends Fragment {
private static final String TAG = "NewsFragment";
private ImageSliderAdapter sliderAdapter;
private List<NewsMonth> monthArray;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.news_fragment, container, false);
}
#Override
public void onViewCreated(#NonNull View view,
Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
ViewPager viewPager = view.findViewById(R.id.view_pager);
sliderAdapter = new ImageSliderAdapter(getContext());
viewPager.setAdapter(sliderAdapter);
initializeData();
RecyclerView recyclerView = view.findViewById(R.id.newsList);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
NewsAdapter adapter = new NewsAdapter(monthArray); /*this.getContext(), R.layout.news_item, monthArray*/
recyclerView.setAdapter(adapter);
}
private void initializeData() {
monthArray = new ArrayList<>();
monthArray.add(new NewsMonth("www.ya.ru", "Январь", null));
monthArray.add(new NewsMonth("www.on.ru", "Февраль", null));
monthArray.add(new NewsMonth("www.ti.ru", "Март", null));
}
}
My XML files - recycle list and card item:
...
....
...
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/newsLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:orientation="vertical"
android:padding="8dp">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
layout_constraintEnd_toStartOf="#+id/newsList"
android:layout_width="match_parent"
android:layout_height="103dp"
app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</android.support.v4.view.ViewPager>
<ScrollView
android:id="#+id/newsScroll"
android:layout_width="match_parent"
android:layout_height="433dp"
android:paddingEnd="#dimen/fab_margin"
app:layout_anchor="#+id/view_pager"
app:layout_anchorGravity="bottom"
app:layout_constraintTop_toBottomOf="#id/view_pager"
tools:layout_constraintTop_toBottomOf="#+id/view_pager"
android:paddingRight="#dimen/fab_margin">
<android.support.v7.widget.RecyclerView
android:id="#+id/newsList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|bottom|left|right"
android:orientation="vertical"
app:layout_anchor="#+id/view_pager"
app:layout_anchorGravity="bottom|center"
app:layout_constraintTop_toBottomOf="#id/view_pager"
tools:layout_editor_absoluteX="3dp"
tools:layout_editor_absoluteY="112dp">
</android.support.v7.widget.RecyclerView>
</ScrollView>
and card item:
a few characters of text so that the stack overflow does not swear
a few characters of text so that the stack overflow does not swear
a few characters of text so that the stack overflow does not swear
a few characters of text so that the stack overflow does not swear
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/cv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="#color/black"
app:cardCornerRadius="8dp"
app:cardUseCompatPadding="true"
app:contentPadding="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<TextView
android:id="#+id/news_label"
android:layout_width="255dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginTop="5dp"
android:background="#color/colorAccent"
tools:text="Who is.. James bond??!" />
<TextView
android:id="#+id/news_category"
android:layout_width="60dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/news_label"
android:layout_alignBottom="#+id/news_label"
android:layout_toEndOf="#+id/news_label"
android:layout_toRightOf="#+id/news_label"
android:background="#android:color/holo_green_light"
tools:text="Artist" />
</RelativeLayout>
<TextView
android:id="#+id/month_name"
android:layout_width="150dp"
android:layout_height="20dp"
android:layout_alignParentTop="true"
android:background="#color/colorPrimaryDark"
android:fontFamily="sans-serif-condensed"
android:gravity="center"
android:textSize="16sp"
android:textStyle="bold"
tools:text="Июнь" />
Do not write findViewById() statements inside OnCreateView.
Only use OnCreateView() for inflating the view.
Write the findViewById() methods in the OnViewCreated() method, which calls as soon as the view creation is completed.
By writing findViewById() in onCreateView(), you are trying to find a view while the container View is still in the process of creation and your view might not have been created yet which results in returning a null.

scrolling large image android

good morning i would like to scroll a large image in my Android app the size of my image is 800 * 3782 px
every time i get error of memory the size of the image is 1.7Mb with 72 dpi resolution.
this is the xml :
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<HorizontalScrollView
android:id="#+id/horizontalScrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ScrollView
android:id="#+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</ScrollView>
</HorizontalScrollView>
</LinearLayout>
this the java class:
public class About extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
ImageView iv = (ImageView) findViewById(R.id.imageView1);
Resources res = getResources();
BitmapDrawable bitmap = (BitmapDrawable) res.
getDrawable(R.drawable.aboutscroll);
int imgW = bitmap.getIntrinsicWidth();
int imgH = bitmap.getIntrinsicHeight();
iv.setImageDrawable(bitmap);
ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) iv.getLayoutParams();
params.width = imgW;
params.height = imgH;
}
}
i got this trace of error :
08-27 09:51:10.175: E/AndroidRuntime(1578): FATAL EXCEPTION: main
08-27 09:51:10.175: E/AndroidRuntime(1578): java.lang.OutOfMemoryError
08-27 09:51:10.175: E/AndroidRuntime(1578): at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
08-27 09:51:10.175: E/AndroidRuntime(1578): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
if someone can help me please.
"Out of memory error" means image file is too big.. if you reduce, then no more error. :)